10b57cec5SDimitry Andric //===- CompilerInvocation.cpp ---------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "clang/Frontend/CompilerInvocation.h" 100b57cec5SDimitry Andric #include "TestModuleFileExtension.h" 110b57cec5SDimitry Andric #include "clang/Basic/Builtins.h" 120b57cec5SDimitry Andric #include "clang/Basic/CharInfo.h" 130b57cec5SDimitry Andric #include "clang/Basic/CodeGenOptions.h" 140b57cec5SDimitry Andric #include "clang/Basic/CommentOptions.h" 150b57cec5SDimitry Andric #include "clang/Basic/Diagnostic.h" 16e8d8bef9SDimitry Andric #include "clang/Basic/DiagnosticDriver.h" 170b57cec5SDimitry Andric #include "clang/Basic/DiagnosticOptions.h" 180b57cec5SDimitry Andric #include "clang/Basic/FileSystemOptions.h" 190b57cec5SDimitry Andric #include "clang/Basic/LLVM.h" 200b57cec5SDimitry Andric #include "clang/Basic/LangOptions.h" 21a7dea167SDimitry Andric #include "clang/Basic/LangStandard.h" 220b57cec5SDimitry Andric #include "clang/Basic/ObjCRuntime.h" 230b57cec5SDimitry Andric #include "clang/Basic/Sanitizers.h" 240b57cec5SDimitry Andric #include "clang/Basic/SourceLocation.h" 250b57cec5SDimitry Andric #include "clang/Basic/TargetOptions.h" 260b57cec5SDimitry Andric #include "clang/Basic/Version.h" 270b57cec5SDimitry Andric #include "clang/Basic/Visibility.h" 280b57cec5SDimitry Andric #include "clang/Basic/XRayInstr.h" 290b57cec5SDimitry Andric #include "clang/Config/config.h" 300b57cec5SDimitry Andric #include "clang/Driver/Driver.h" 310b57cec5SDimitry Andric #include "clang/Driver/DriverDiagnostic.h" 320b57cec5SDimitry Andric #include "clang/Driver/Options.h" 330b57cec5SDimitry Andric #include "clang/Frontend/CommandLineSourceLoc.h" 340b57cec5SDimitry Andric #include "clang/Frontend/DependencyOutputOptions.h" 350b57cec5SDimitry Andric #include "clang/Frontend/FrontendDiagnostic.h" 360b57cec5SDimitry Andric #include "clang/Frontend/FrontendOptions.h" 370b57cec5SDimitry Andric #include "clang/Frontend/FrontendPluginRegistry.h" 380b57cec5SDimitry Andric #include "clang/Frontend/MigratorOptions.h" 390b57cec5SDimitry Andric #include "clang/Frontend/PreprocessorOutputOptions.h" 40fe6060f1SDimitry Andric #include "clang/Frontend/TextDiagnosticBuffer.h" 410b57cec5SDimitry Andric #include "clang/Frontend/Utils.h" 420b57cec5SDimitry Andric #include "clang/Lex/HeaderSearchOptions.h" 430b57cec5SDimitry Andric #include "clang/Lex/PreprocessorOptions.h" 440b57cec5SDimitry Andric #include "clang/Sema/CodeCompleteOptions.h" 455ffd83dbSDimitry Andric #include "clang/Serialization/ASTBitCodes.h" 460b57cec5SDimitry Andric #include "clang/Serialization/ModuleFileExtension.h" 470b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" 480b57cec5SDimitry Andric #include "llvm/ADT/APInt.h" 490b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 500b57cec5SDimitry Andric #include "llvm/ADT/CachedHashString.h" 515ffd83dbSDimitry Andric #include "llvm/ADT/FloatingPointMode.h" 520b57cec5SDimitry Andric #include "llvm/ADT/Hashing.h" 53fe6060f1SDimitry Andric #include "llvm/ADT/STLExtras.h" 540b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 550b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 560b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 570b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h" 580b57cec5SDimitry Andric #include "llvm/ADT/Twine.h" 59e8d8bef9SDimitry Andric #include "llvm/Config/llvm-config.h" 6006c3fb27SDimitry Andric #include "llvm/Frontend/Debug/Options.h" 610b57cec5SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h" 620b57cec5SDimitry Andric #include "llvm/Linker/Linker.h" 630b57cec5SDimitry Andric #include "llvm/MC/MCTargetOptions.h" 640b57cec5SDimitry Andric #include "llvm/Option/Arg.h" 650b57cec5SDimitry Andric #include "llvm/Option/ArgList.h" 660b57cec5SDimitry Andric #include "llvm/Option/OptSpecifier.h" 670b57cec5SDimitry Andric #include "llvm/Option/OptTable.h" 680b57cec5SDimitry Andric #include "llvm/Option/Option.h" 690b57cec5SDimitry Andric #include "llvm/ProfileData/InstrProfReader.h" 70e8d8bef9SDimitry Andric #include "llvm/Remarks/HotnessThresholdParser.h" 710b57cec5SDimitry Andric #include "llvm/Support/CodeGen.h" 720b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 730b57cec5SDimitry Andric #include "llvm/Support/Error.h" 740b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 750b57cec5SDimitry Andric #include "llvm/Support/ErrorOr.h" 760b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h" 77349cc55cSDimitry Andric #include "llvm/Support/HashBuilder.h" 780b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 790b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 800b57cec5SDimitry Andric #include "llvm/Support/Path.h" 810b57cec5SDimitry Andric #include "llvm/Support/Process.h" 820b57cec5SDimitry Andric #include "llvm/Support/Regex.h" 830b57cec5SDimitry Andric #include "llvm/Support/VersionTuple.h" 840b57cec5SDimitry Andric #include "llvm/Support/VirtualFileSystem.h" 850b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 860b57cec5SDimitry Andric #include "llvm/Target/TargetOptions.h" 8706c3fb27SDimitry Andric #include "llvm/TargetParser/Host.h" 8806c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h" 890b57cec5SDimitry Andric #include <algorithm> 900b57cec5SDimitry Andric #include <atomic> 910b57cec5SDimitry Andric #include <cassert> 920b57cec5SDimitry Andric #include <cstddef> 930b57cec5SDimitry Andric #include <cstring> 94bdd1243dSDimitry Andric #include <ctime> 9581ad6265SDimitry Andric #include <fstream> 96bdd1243dSDimitry Andric #include <limits> 970b57cec5SDimitry Andric #include <memory> 98bdd1243dSDimitry Andric #include <optional> 990b57cec5SDimitry Andric #include <string> 1000b57cec5SDimitry Andric #include <tuple> 101e8d8bef9SDimitry Andric #include <type_traits> 1020b57cec5SDimitry Andric #include <utility> 1030b57cec5SDimitry Andric #include <vector> 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric using namespace clang; 1060b57cec5SDimitry Andric using namespace driver; 1070b57cec5SDimitry Andric using namespace options; 1080b57cec5SDimitry Andric using namespace llvm::opt; 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 11181ad6265SDimitry Andric // Helpers. 11281ad6265SDimitry Andric //===----------------------------------------------------------------------===// 11381ad6265SDimitry Andric 11481ad6265SDimitry Andric // Parse misexpect tolerance argument value. 11581ad6265SDimitry Andric // Valid option values are integers in the range [0, 100) 116bdd1243dSDimitry Andric static Expected<std::optional<uint32_t>> parseToleranceOption(StringRef Arg) { 117bdd1243dSDimitry Andric uint32_t Val; 11881ad6265SDimitry Andric if (Arg.getAsInteger(10, Val)) 11981ad6265SDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 12081ad6265SDimitry Andric "Not an integer: %s", Arg.data()); 12181ad6265SDimitry Andric return Val; 12281ad6265SDimitry Andric } 12381ad6265SDimitry Andric 12481ad6265SDimitry Andric //===----------------------------------------------------------------------===// 1250b57cec5SDimitry Andric // Initialization. 1260b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 1270b57cec5SDimitry Andric 1285f757f3fSDimitry Andric namespace { 1295f757f3fSDimitry Andric template <class T> std::shared_ptr<T> make_shared_copy(const T &X) { 1305f757f3fSDimitry Andric return std::make_shared<T>(X); 1315f757f3fSDimitry Andric } 1320b57cec5SDimitry Andric 1335f757f3fSDimitry Andric template <class T> 1345f757f3fSDimitry Andric llvm::IntrusiveRefCntPtr<T> makeIntrusiveRefCntCopy(const T &X) { 1355f757f3fSDimitry Andric return llvm::makeIntrusiveRefCnt<T>(X); 1365f757f3fSDimitry Andric } 1375f757f3fSDimitry Andric } // namespace 1380b57cec5SDimitry Andric 1395f757f3fSDimitry Andric CompilerInvocationBase::CompilerInvocationBase() 1405f757f3fSDimitry Andric : LangOpts(std::make_shared<LangOptions>()), 1415f757f3fSDimitry Andric TargetOpts(std::make_shared<TargetOptions>()), 1425f757f3fSDimitry Andric DiagnosticOpts(llvm::makeIntrusiveRefCnt<DiagnosticOptions>()), 1435f757f3fSDimitry Andric HSOpts(std::make_shared<HeaderSearchOptions>()), 1445f757f3fSDimitry Andric PPOpts(std::make_shared<PreprocessorOptions>()), 1455f757f3fSDimitry Andric AnalyzerOpts(llvm::makeIntrusiveRefCnt<AnalyzerOptions>()), 1465f757f3fSDimitry Andric MigratorOpts(std::make_shared<MigratorOptions>()), 1475f757f3fSDimitry Andric APINotesOpts(std::make_shared<APINotesOptions>()), 1485f757f3fSDimitry Andric CodeGenOpts(std::make_shared<CodeGenOptions>()), 1495f757f3fSDimitry Andric FSOpts(std::make_shared<FileSystemOptions>()), 1505f757f3fSDimitry Andric FrontendOpts(std::make_shared<FrontendOptions>()), 1515f757f3fSDimitry Andric DependencyOutputOpts(std::make_shared<DependencyOutputOptions>()), 1525f757f3fSDimitry Andric PreprocessorOutputOpts(std::make_shared<PreprocessorOutputOptions>()) {} 153fe6060f1SDimitry Andric 1545f757f3fSDimitry Andric CompilerInvocationBase & 1555f757f3fSDimitry Andric CompilerInvocationBase::deep_copy_assign(const CompilerInvocationBase &X) { 1565f757f3fSDimitry Andric if (this != &X) { 1575f757f3fSDimitry Andric LangOpts = make_shared_copy(X.getLangOpts()); 1585f757f3fSDimitry Andric TargetOpts = make_shared_copy(X.getTargetOpts()); 1595f757f3fSDimitry Andric DiagnosticOpts = makeIntrusiveRefCntCopy(X.getDiagnosticOpts()); 1605f757f3fSDimitry Andric HSOpts = make_shared_copy(X.getHeaderSearchOpts()); 1615f757f3fSDimitry Andric PPOpts = make_shared_copy(X.getPreprocessorOpts()); 1625f757f3fSDimitry Andric AnalyzerOpts = makeIntrusiveRefCntCopy(X.getAnalyzerOpts()); 1635f757f3fSDimitry Andric MigratorOpts = make_shared_copy(X.getMigratorOpts()); 1645f757f3fSDimitry Andric APINotesOpts = make_shared_copy(X.getAPINotesOpts()); 1655f757f3fSDimitry Andric CodeGenOpts = make_shared_copy(X.getCodeGenOpts()); 1665f757f3fSDimitry Andric FSOpts = make_shared_copy(X.getFileSystemOpts()); 1675f757f3fSDimitry Andric FrontendOpts = make_shared_copy(X.getFrontendOpts()); 1685f757f3fSDimitry Andric DependencyOutputOpts = make_shared_copy(X.getDependencyOutputOpts()); 1695f757f3fSDimitry Andric PreprocessorOutputOpts = make_shared_copy(X.getPreprocessorOutputOpts()); 1705f757f3fSDimitry Andric } 171fe6060f1SDimitry Andric return *this; 172fe6060f1SDimitry Andric } 173fe6060f1SDimitry Andric 1745f757f3fSDimitry Andric CompilerInvocationBase & 1755f757f3fSDimitry Andric CompilerInvocationBase::shallow_copy_assign(const CompilerInvocationBase &X) { 1765f757f3fSDimitry Andric if (this != &X) { 1775f757f3fSDimitry Andric LangOpts = X.LangOpts; 1785f757f3fSDimitry Andric TargetOpts = X.TargetOpts; 1795f757f3fSDimitry Andric DiagnosticOpts = X.DiagnosticOpts; 1805f757f3fSDimitry Andric HSOpts = X.HSOpts; 1815f757f3fSDimitry Andric PPOpts = X.PPOpts; 1825f757f3fSDimitry Andric AnalyzerOpts = X.AnalyzerOpts; 1835f757f3fSDimitry Andric MigratorOpts = X.MigratorOpts; 1845f757f3fSDimitry Andric APINotesOpts = X.APINotesOpts; 1855f757f3fSDimitry Andric CodeGenOpts = X.CodeGenOpts; 1865f757f3fSDimitry Andric FSOpts = X.FSOpts; 1875f757f3fSDimitry Andric FrontendOpts = X.FrontendOpts; 1885f757f3fSDimitry Andric DependencyOutputOpts = X.DependencyOutputOpts; 1895f757f3fSDimitry Andric PreprocessorOutputOpts = X.PreprocessorOutputOpts; 1905f757f3fSDimitry Andric } 1915f757f3fSDimitry Andric return *this; 1925f757f3fSDimitry Andric } 193fe6060f1SDimitry Andric 1940fca6ea1SDimitry Andric CompilerInvocation::CompilerInvocation(const CowCompilerInvocation &X) 1950fca6ea1SDimitry Andric : CompilerInvocationBase(EmptyConstructor{}) { 1960fca6ea1SDimitry Andric CompilerInvocationBase::deep_copy_assign(X); 1970fca6ea1SDimitry Andric } 1980fca6ea1SDimitry Andric 1990fca6ea1SDimitry Andric CompilerInvocation & 2000fca6ea1SDimitry Andric CompilerInvocation::operator=(const CowCompilerInvocation &X) { 2010fca6ea1SDimitry Andric CompilerInvocationBase::deep_copy_assign(X); 2020fca6ea1SDimitry Andric return *this; 2030fca6ea1SDimitry Andric } 2040fca6ea1SDimitry Andric 2055f757f3fSDimitry Andric namespace { 2065f757f3fSDimitry Andric template <typename T> 2075f757f3fSDimitry Andric T &ensureOwned(std::shared_ptr<T> &Storage) { 2085f757f3fSDimitry Andric if (Storage.use_count() > 1) 2095f757f3fSDimitry Andric Storage = std::make_shared<T>(*Storage); 2105f757f3fSDimitry Andric return *Storage; 2115f757f3fSDimitry Andric } 2125f757f3fSDimitry Andric 2135f757f3fSDimitry Andric template <typename T> 2145f757f3fSDimitry Andric T &ensureOwned(llvm::IntrusiveRefCntPtr<T> &Storage) { 2155f757f3fSDimitry Andric if (Storage.useCount() > 1) 2165f757f3fSDimitry Andric Storage = llvm::makeIntrusiveRefCnt<T>(*Storage); 2175f757f3fSDimitry Andric return *Storage; 2185f757f3fSDimitry Andric } 2195f757f3fSDimitry Andric } // namespace 2205f757f3fSDimitry Andric 2215f757f3fSDimitry Andric LangOptions &CowCompilerInvocation::getMutLangOpts() { 2225f757f3fSDimitry Andric return ensureOwned(LangOpts); 2235f757f3fSDimitry Andric } 2245f757f3fSDimitry Andric 2255f757f3fSDimitry Andric TargetOptions &CowCompilerInvocation::getMutTargetOpts() { 2265f757f3fSDimitry Andric return ensureOwned(TargetOpts); 2275f757f3fSDimitry Andric } 2285f757f3fSDimitry Andric 2295f757f3fSDimitry Andric DiagnosticOptions &CowCompilerInvocation::getMutDiagnosticOpts() { 2305f757f3fSDimitry Andric return ensureOwned(DiagnosticOpts); 2315f757f3fSDimitry Andric } 2325f757f3fSDimitry Andric 2335f757f3fSDimitry Andric HeaderSearchOptions &CowCompilerInvocation::getMutHeaderSearchOpts() { 2345f757f3fSDimitry Andric return ensureOwned(HSOpts); 2355f757f3fSDimitry Andric } 2365f757f3fSDimitry Andric 2375f757f3fSDimitry Andric PreprocessorOptions &CowCompilerInvocation::getMutPreprocessorOpts() { 2385f757f3fSDimitry Andric return ensureOwned(PPOpts); 2395f757f3fSDimitry Andric } 2405f757f3fSDimitry Andric 2415f757f3fSDimitry Andric AnalyzerOptions &CowCompilerInvocation::getMutAnalyzerOpts() { 2425f757f3fSDimitry Andric return ensureOwned(AnalyzerOpts); 2435f757f3fSDimitry Andric } 2445f757f3fSDimitry Andric 2455f757f3fSDimitry Andric MigratorOptions &CowCompilerInvocation::getMutMigratorOpts() { 2465f757f3fSDimitry Andric return ensureOwned(MigratorOpts); 2475f757f3fSDimitry Andric } 2485f757f3fSDimitry Andric 2495f757f3fSDimitry Andric APINotesOptions &CowCompilerInvocation::getMutAPINotesOpts() { 2505f757f3fSDimitry Andric return ensureOwned(APINotesOpts); 2515f757f3fSDimitry Andric } 2525f757f3fSDimitry Andric 2535f757f3fSDimitry Andric CodeGenOptions &CowCompilerInvocation::getMutCodeGenOpts() { 2545f757f3fSDimitry Andric return ensureOwned(CodeGenOpts); 2555f757f3fSDimitry Andric } 2565f757f3fSDimitry Andric 2575f757f3fSDimitry Andric FileSystemOptions &CowCompilerInvocation::getMutFileSystemOpts() { 2585f757f3fSDimitry Andric return ensureOwned(FSOpts); 2595f757f3fSDimitry Andric } 2605f757f3fSDimitry Andric 2615f757f3fSDimitry Andric FrontendOptions &CowCompilerInvocation::getMutFrontendOpts() { 2625f757f3fSDimitry Andric return ensureOwned(FrontendOpts); 2635f757f3fSDimitry Andric } 2645f757f3fSDimitry Andric 2655f757f3fSDimitry Andric DependencyOutputOptions &CowCompilerInvocation::getMutDependencyOutputOpts() { 2665f757f3fSDimitry Andric return ensureOwned(DependencyOutputOpts); 2675f757f3fSDimitry Andric } 2685f757f3fSDimitry Andric 2695f757f3fSDimitry Andric PreprocessorOutputOptions & 2705f757f3fSDimitry Andric CowCompilerInvocation::getMutPreprocessorOutputOpts() { 2715f757f3fSDimitry Andric return ensureOwned(PreprocessorOutputOpts); 2725f757f3fSDimitry Andric } 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2755ffd83dbSDimitry Andric // Normalizers 2765ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 2775ffd83dbSDimitry Andric 2785f757f3fSDimitry Andric using ArgumentConsumer = CompilerInvocation::ArgumentConsumer; 2795f757f3fSDimitry Andric 2805ffd83dbSDimitry Andric #define SIMPLE_ENUM_VALUE_TABLE 2815ffd83dbSDimitry Andric #include "clang/Driver/Options.inc" 2825ffd83dbSDimitry Andric #undef SIMPLE_ENUM_VALUE_TABLE 2835ffd83dbSDimitry Andric 284bdd1243dSDimitry Andric static std::optional<bool> normalizeSimpleFlag(OptSpecifier Opt, 285fe6060f1SDimitry Andric unsigned TableIndex, 286fe6060f1SDimitry Andric const ArgList &Args, 287fe6060f1SDimitry Andric DiagnosticsEngine &Diags) { 288e8d8bef9SDimitry Andric if (Args.hasArg(Opt)) 289e8d8bef9SDimitry Andric return true; 290bdd1243dSDimitry Andric return std::nullopt; 291e8d8bef9SDimitry Andric } 292e8d8bef9SDimitry Andric 293bdd1243dSDimitry Andric static std::optional<bool> normalizeSimpleNegativeFlag(OptSpecifier Opt, 294bdd1243dSDimitry Andric unsigned, 2955ffd83dbSDimitry Andric const ArgList &Args, 296fe6060f1SDimitry Andric DiagnosticsEngine &) { 297e8d8bef9SDimitry Andric if (Args.hasArg(Opt)) 298e8d8bef9SDimitry Andric return false; 299bdd1243dSDimitry Andric return std::nullopt; 300e8d8bef9SDimitry Andric } 301e8d8bef9SDimitry Andric 302e8d8bef9SDimitry Andric /// The tblgen-erated code passes in a fifth parameter of an arbitrary type, but 303e8d8bef9SDimitry Andric /// denormalizeSimpleFlags never looks at it. Avoid bloating compile-time with 304e8d8bef9SDimitry Andric /// unnecessary template instantiations and just ignore it with a variadic 305e8d8bef9SDimitry Andric /// argument. 3065f757f3fSDimitry Andric static void denormalizeSimpleFlag(ArgumentConsumer Consumer, 3075f757f3fSDimitry Andric const Twine &Spelling, Option::OptionClass, 3085f757f3fSDimitry Andric unsigned, /*T*/...) { 3095f757f3fSDimitry Andric Consumer(Spelling); 310e8d8bef9SDimitry Andric } 311e8d8bef9SDimitry Andric 312e8d8bef9SDimitry Andric template <typename T> static constexpr bool is_uint64_t_convertible() { 313bdd1243dSDimitry Andric return !std::is_same_v<T, uint64_t> && llvm::is_integral_or_enum<T>::value; 314e8d8bef9SDimitry Andric } 315e8d8bef9SDimitry Andric 316e8d8bef9SDimitry Andric template <typename T, 317e8d8bef9SDimitry Andric std::enable_if_t<!is_uint64_t_convertible<T>(), bool> = false> 318e8d8bef9SDimitry Andric static auto makeFlagToValueNormalizer(T Value) { 319e8d8bef9SDimitry Andric return [Value](OptSpecifier Opt, unsigned, const ArgList &Args, 320bdd1243dSDimitry Andric DiagnosticsEngine &) -> std::optional<T> { 321e8d8bef9SDimitry Andric if (Args.hasArg(Opt)) 322e8d8bef9SDimitry Andric return Value; 323bdd1243dSDimitry Andric return std::nullopt; 324e8d8bef9SDimitry Andric }; 325e8d8bef9SDimitry Andric } 326e8d8bef9SDimitry Andric 327e8d8bef9SDimitry Andric template <typename T, 328e8d8bef9SDimitry Andric std::enable_if_t<is_uint64_t_convertible<T>(), bool> = false> 329e8d8bef9SDimitry Andric static auto makeFlagToValueNormalizer(T Value) { 330e8d8bef9SDimitry Andric return makeFlagToValueNormalizer(uint64_t(Value)); 331e8d8bef9SDimitry Andric } 332e8d8bef9SDimitry Andric 333e8d8bef9SDimitry Andric static auto makeBooleanOptionNormalizer(bool Value, bool OtherValue, 334e8d8bef9SDimitry Andric OptSpecifier OtherOpt) { 335bdd1243dSDimitry Andric return [Value, OtherValue, 336bdd1243dSDimitry Andric OtherOpt](OptSpecifier Opt, unsigned, const ArgList &Args, 337bdd1243dSDimitry Andric DiagnosticsEngine &) -> std::optional<bool> { 338e8d8bef9SDimitry Andric if (const Arg *A = Args.getLastArg(Opt, OtherOpt)) { 339e8d8bef9SDimitry Andric return A->getOption().matches(Opt) ? Value : OtherValue; 340e8d8bef9SDimitry Andric } 341bdd1243dSDimitry Andric return std::nullopt; 342e8d8bef9SDimitry Andric }; 343e8d8bef9SDimitry Andric } 344e8d8bef9SDimitry Andric 345e8d8bef9SDimitry Andric static auto makeBooleanOptionDenormalizer(bool Value) { 3465f757f3fSDimitry Andric return [Value](ArgumentConsumer Consumer, const Twine &Spelling, 3475f757f3fSDimitry Andric Option::OptionClass, unsigned, bool KeyPath) { 348e8d8bef9SDimitry Andric if (KeyPath == Value) 3495f757f3fSDimitry Andric Consumer(Spelling); 350e8d8bef9SDimitry Andric }; 351e8d8bef9SDimitry Andric } 352e8d8bef9SDimitry Andric 3535f757f3fSDimitry Andric static void denormalizeStringImpl(ArgumentConsumer Consumer, 3545f757f3fSDimitry Andric const Twine &Spelling, 355e8d8bef9SDimitry Andric Option::OptionClass OptClass, unsigned, 356fe6060f1SDimitry Andric const Twine &Value) { 357e8d8bef9SDimitry Andric switch (OptClass) { 358e8d8bef9SDimitry Andric case Option::SeparateClass: 359e8d8bef9SDimitry Andric case Option::JoinedOrSeparateClass: 360fe6060f1SDimitry Andric case Option::JoinedAndSeparateClass: 3615f757f3fSDimitry Andric Consumer(Spelling); 3625f757f3fSDimitry Andric Consumer(Value); 363e8d8bef9SDimitry Andric break; 364e8d8bef9SDimitry Andric case Option::JoinedClass: 365fe6060f1SDimitry Andric case Option::CommaJoinedClass: 3665f757f3fSDimitry Andric Consumer(Spelling + Value); 367e8d8bef9SDimitry Andric break; 368e8d8bef9SDimitry Andric default: 369e8d8bef9SDimitry Andric llvm_unreachable("Cannot denormalize an option with option class " 370e8d8bef9SDimitry Andric "incompatible with string denormalization."); 371e8d8bef9SDimitry Andric } 372e8d8bef9SDimitry Andric } 373e8d8bef9SDimitry Andric 374e8d8bef9SDimitry Andric template <typename T> 3755f757f3fSDimitry Andric static void denormalizeString(ArgumentConsumer Consumer, const Twine &Spelling, 3765f757f3fSDimitry Andric Option::OptionClass OptClass, unsigned TableIndex, 3775f757f3fSDimitry Andric T Value) { 3785f757f3fSDimitry Andric denormalizeStringImpl(Consumer, Spelling, OptClass, TableIndex, Twine(Value)); 379e8d8bef9SDimitry Andric } 380e8d8bef9SDimitry Andric 381bdd1243dSDimitry Andric static std::optional<SimpleEnumValue> 382e8d8bef9SDimitry Andric findValueTableByName(const SimpleEnumValueTable &Table, StringRef Name) { 383e8d8bef9SDimitry Andric for (int I = 0, E = Table.Size; I != E; ++I) 384e8d8bef9SDimitry Andric if (Name == Table.Table[I].Name) 385e8d8bef9SDimitry Andric return Table.Table[I]; 386e8d8bef9SDimitry Andric 387bdd1243dSDimitry Andric return std::nullopt; 388e8d8bef9SDimitry Andric } 389e8d8bef9SDimitry Andric 390bdd1243dSDimitry Andric static std::optional<SimpleEnumValue> 391e8d8bef9SDimitry Andric findValueTableByValue(const SimpleEnumValueTable &Table, unsigned Value) { 392e8d8bef9SDimitry Andric for (int I = 0, E = Table.Size; I != E; ++I) 393e8d8bef9SDimitry Andric if (Value == Table.Table[I].Value) 394e8d8bef9SDimitry Andric return Table.Table[I]; 395e8d8bef9SDimitry Andric 396bdd1243dSDimitry Andric return std::nullopt; 397e8d8bef9SDimitry Andric } 398e8d8bef9SDimitry Andric 399bdd1243dSDimitry Andric static std::optional<unsigned> normalizeSimpleEnum(OptSpecifier Opt, 400fe6060f1SDimitry Andric unsigned TableIndex, 401fe6060f1SDimitry Andric const ArgList &Args, 402fe6060f1SDimitry Andric DiagnosticsEngine &Diags) { 4035ffd83dbSDimitry Andric assert(TableIndex < SimpleEnumValueTablesSize); 4045ffd83dbSDimitry Andric const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex]; 4055ffd83dbSDimitry Andric 4065ffd83dbSDimitry Andric auto *Arg = Args.getLastArg(Opt); 4075ffd83dbSDimitry Andric if (!Arg) 408bdd1243dSDimitry Andric return std::nullopt; 4095ffd83dbSDimitry Andric 4105ffd83dbSDimitry Andric StringRef ArgValue = Arg->getValue(); 411e8d8bef9SDimitry Andric if (auto MaybeEnumVal = findValueTableByName(Table, ArgValue)) 412e8d8bef9SDimitry Andric return MaybeEnumVal->Value; 4135ffd83dbSDimitry Andric 4145ffd83dbSDimitry Andric Diags.Report(diag::err_drv_invalid_value) 4155ffd83dbSDimitry Andric << Arg->getAsString(Args) << ArgValue; 416bdd1243dSDimitry Andric return std::nullopt; 4175ffd83dbSDimitry Andric } 4185ffd83dbSDimitry Andric 4195f757f3fSDimitry Andric static void denormalizeSimpleEnumImpl(ArgumentConsumer Consumer, 4205f757f3fSDimitry Andric const Twine &Spelling, 421e8d8bef9SDimitry Andric Option::OptionClass OptClass, 4225ffd83dbSDimitry Andric unsigned TableIndex, unsigned Value) { 4235ffd83dbSDimitry Andric assert(TableIndex < SimpleEnumValueTablesSize); 4245ffd83dbSDimitry Andric const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex]; 425e8d8bef9SDimitry Andric if (auto MaybeEnumVal = findValueTableByValue(Table, Value)) { 4265f757f3fSDimitry Andric denormalizeString(Consumer, Spelling, OptClass, TableIndex, 427e8d8bef9SDimitry Andric MaybeEnumVal->Name); 428e8d8bef9SDimitry Andric } else { 4295ffd83dbSDimitry Andric llvm_unreachable("The simple enum value was not correctly defined in " 4305ffd83dbSDimitry Andric "the tablegen option description"); 4315ffd83dbSDimitry Andric } 432e8d8bef9SDimitry Andric } 4335ffd83dbSDimitry Andric 434e8d8bef9SDimitry Andric template <typename T> 4355f757f3fSDimitry Andric static void denormalizeSimpleEnum(ArgumentConsumer Consumer, 4365f757f3fSDimitry Andric const Twine &Spelling, 437e8d8bef9SDimitry Andric Option::OptionClass OptClass, 438e8d8bef9SDimitry Andric unsigned TableIndex, T Value) { 4395f757f3fSDimitry Andric return denormalizeSimpleEnumImpl(Consumer, Spelling, OptClass, TableIndex, 440e8d8bef9SDimitry Andric static_cast<unsigned>(Value)); 441e8d8bef9SDimitry Andric } 442e8d8bef9SDimitry Andric 443bdd1243dSDimitry Andric static std::optional<std::string> normalizeString(OptSpecifier Opt, 444bdd1243dSDimitry Andric int TableIndex, 445e8d8bef9SDimitry Andric const ArgList &Args, 446fe6060f1SDimitry Andric DiagnosticsEngine &Diags) { 447e8d8bef9SDimitry Andric auto *Arg = Args.getLastArg(Opt); 448e8d8bef9SDimitry Andric if (!Arg) 449bdd1243dSDimitry Andric return std::nullopt; 450e8d8bef9SDimitry Andric return std::string(Arg->getValue()); 451e8d8bef9SDimitry Andric } 452e8d8bef9SDimitry Andric 453e8d8bef9SDimitry Andric template <typename IntTy> 454bdd1243dSDimitry Andric static std::optional<IntTy> normalizeStringIntegral(OptSpecifier Opt, int, 455fe6060f1SDimitry Andric const ArgList &Args, 456fe6060f1SDimitry Andric DiagnosticsEngine &Diags) { 457e8d8bef9SDimitry Andric auto *Arg = Args.getLastArg(Opt); 458e8d8bef9SDimitry Andric if (!Arg) 459bdd1243dSDimitry Andric return std::nullopt; 460e8d8bef9SDimitry Andric IntTy Res; 461e8d8bef9SDimitry Andric if (StringRef(Arg->getValue()).getAsInteger(0, Res)) { 462e8d8bef9SDimitry Andric Diags.Report(diag::err_drv_invalid_int_value) 463e8d8bef9SDimitry Andric << Arg->getAsString(Args) << Arg->getValue(); 464bdd1243dSDimitry Andric return std::nullopt; 465e8d8bef9SDimitry Andric } 466e8d8bef9SDimitry Andric return Res; 467e8d8bef9SDimitry Andric } 468e8d8bef9SDimitry Andric 469bdd1243dSDimitry Andric static std::optional<std::vector<std::string>> 470e8d8bef9SDimitry Andric normalizeStringVector(OptSpecifier Opt, int, const ArgList &Args, 471fe6060f1SDimitry Andric DiagnosticsEngine &) { 472e8d8bef9SDimitry Andric return Args.getAllArgValues(Opt); 473e8d8bef9SDimitry Andric } 474e8d8bef9SDimitry Andric 4755f757f3fSDimitry Andric static void denormalizeStringVector(ArgumentConsumer Consumer, 4765f757f3fSDimitry Andric const Twine &Spelling, 477e8d8bef9SDimitry Andric Option::OptionClass OptClass, 4785ffd83dbSDimitry Andric unsigned TableIndex, 479e8d8bef9SDimitry Andric const std::vector<std::string> &Values) { 480e8d8bef9SDimitry Andric switch (OptClass) { 481e8d8bef9SDimitry Andric case Option::CommaJoinedClass: { 482e8d8bef9SDimitry Andric std::string CommaJoinedValue; 483e8d8bef9SDimitry Andric if (!Values.empty()) { 484e8d8bef9SDimitry Andric CommaJoinedValue.append(Values.front()); 485e8d8bef9SDimitry Andric for (const std::string &Value : llvm::drop_begin(Values, 1)) { 486e8d8bef9SDimitry Andric CommaJoinedValue.append(","); 487e8d8bef9SDimitry Andric CommaJoinedValue.append(Value); 488e8d8bef9SDimitry Andric } 489e8d8bef9SDimitry Andric } 4905f757f3fSDimitry Andric denormalizeString(Consumer, Spelling, Option::OptionClass::JoinedClass, 491e8d8bef9SDimitry Andric TableIndex, CommaJoinedValue); 492e8d8bef9SDimitry Andric break; 493e8d8bef9SDimitry Andric } 494e8d8bef9SDimitry Andric case Option::JoinedClass: 495e8d8bef9SDimitry Andric case Option::SeparateClass: 496e8d8bef9SDimitry Andric case Option::JoinedOrSeparateClass: 497e8d8bef9SDimitry Andric for (const std::string &Value : Values) 4985f757f3fSDimitry Andric denormalizeString(Consumer, Spelling, OptClass, TableIndex, Value); 499e8d8bef9SDimitry Andric break; 500e8d8bef9SDimitry Andric default: 501e8d8bef9SDimitry Andric llvm_unreachable("Cannot denormalize an option with option class " 502e8d8bef9SDimitry Andric "incompatible with string vector denormalization."); 503e8d8bef9SDimitry Andric } 5045ffd83dbSDimitry Andric } 5055ffd83dbSDimitry Andric 506bdd1243dSDimitry Andric static std::optional<std::string> normalizeTriple(OptSpecifier Opt, 507bdd1243dSDimitry Andric int TableIndex, 5085ffd83dbSDimitry Andric const ArgList &Args, 509fe6060f1SDimitry Andric DiagnosticsEngine &Diags) { 5105ffd83dbSDimitry Andric auto *Arg = Args.getLastArg(Opt); 5115ffd83dbSDimitry Andric if (!Arg) 512bdd1243dSDimitry Andric return std::nullopt; 5135ffd83dbSDimitry Andric return llvm::Triple::normalize(Arg->getValue()); 5145ffd83dbSDimitry Andric } 5155ffd83dbSDimitry Andric 516e8d8bef9SDimitry Andric template <typename T, typename U> 517e8d8bef9SDimitry Andric static T mergeForwardValue(T KeyPath, U Value) { 518e8d8bef9SDimitry Andric return static_cast<T>(Value); 519e8d8bef9SDimitry Andric } 520e8d8bef9SDimitry Andric 521e8d8bef9SDimitry Andric template <typename T, typename U> static T mergeMaskValue(T KeyPath, U Value) { 522e8d8bef9SDimitry Andric return KeyPath | Value; 523e8d8bef9SDimitry Andric } 524e8d8bef9SDimitry Andric 525e8d8bef9SDimitry Andric template <typename T> static T extractForwardValue(T KeyPath) { 526e8d8bef9SDimitry Andric return KeyPath; 527e8d8bef9SDimitry Andric } 528e8d8bef9SDimitry Andric 529e8d8bef9SDimitry Andric template <typename T, typename U, U Value> 530e8d8bef9SDimitry Andric static T extractMaskValue(T KeyPath) { 531fe6060f1SDimitry Andric return ((KeyPath & Value) == Value) ? static_cast<T>(Value) : T(); 532e8d8bef9SDimitry Andric } 533e8d8bef9SDimitry Andric 534fe6060f1SDimitry Andric #define PARSE_OPTION_WITH_MARSHALLING( \ 5355f757f3fSDimitry Andric ARGS, DIAGS, PREFIX_TYPE, SPELLING, ID, KIND, GROUP, ALIAS, ALIASARGS, \ 5360fca6ea1SDimitry Andric FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES, \ 5370fca6ea1SDimitry Andric SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, \ 5380fca6ea1SDimitry Andric IMPLIED_VALUE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \ 5395f757f3fSDimitry Andric if ((VISIBILITY) & options::CC1Option) { \ 540e8d8bef9SDimitry Andric KEYPATH = MERGER(KEYPATH, DEFAULT_VALUE); \ 541e8d8bef9SDimitry Andric if (IMPLIED_CHECK) \ 542e8d8bef9SDimitry Andric KEYPATH = MERGER(KEYPATH, IMPLIED_VALUE); \ 543e8d8bef9SDimitry Andric if (SHOULD_PARSE) \ 544fe6060f1SDimitry Andric if (auto MaybeValue = NORMALIZER(OPT_##ID, TABLE_INDEX, ARGS, DIAGS)) \ 545e8d8bef9SDimitry Andric KEYPATH = \ 546e8d8bef9SDimitry Andric MERGER(KEYPATH, static_cast<decltype(KEYPATH)>(*MaybeValue)); \ 547e8d8bef9SDimitry Andric } 548e8d8bef9SDimitry Andric 549fe6060f1SDimitry Andric // Capture the extracted value as a lambda argument to avoid potential issues 550fe6060f1SDimitry Andric // with lifetime extension of the reference. 551fe6060f1SDimitry Andric #define GENERATE_OPTION_WITH_MARSHALLING( \ 5525f757f3fSDimitry Andric CONSUMER, PREFIX_TYPE, SPELLING, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, \ 5530fca6ea1SDimitry Andric VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES, \ 5540fca6ea1SDimitry Andric SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, \ 5550fca6ea1SDimitry Andric IMPLIED_VALUE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \ 5565f757f3fSDimitry Andric if ((VISIBILITY) & options::CC1Option) { \ 557fe6060f1SDimitry Andric [&](const auto &Extracted) { \ 558fe6060f1SDimitry Andric if (ALWAYS_EMIT || \ 559fe6060f1SDimitry Andric (Extracted != \ 560fe6060f1SDimitry Andric static_cast<decltype(KEYPATH)>((IMPLIED_CHECK) ? (IMPLIED_VALUE) \ 561fe6060f1SDimitry Andric : (DEFAULT_VALUE)))) \ 5625f757f3fSDimitry Andric DENORMALIZER(CONSUMER, SPELLING, Option::KIND##Class, TABLE_INDEX, \ 5635f757f3fSDimitry Andric Extracted); \ 564fe6060f1SDimitry Andric }(EXTRACTOR(KEYPATH)); \ 565fe6060f1SDimitry Andric } 566fe6060f1SDimitry Andric 56704eeddc0SDimitry Andric static StringRef GetInputKindName(InputKind IK); 568e8d8bef9SDimitry Andric 569fe6060f1SDimitry Andric static bool FixupInvocation(CompilerInvocation &Invocation, 570fe6060f1SDimitry Andric DiagnosticsEngine &Diags, const ArgList &Args, 571e8d8bef9SDimitry Andric InputKind IK) { 572fe6060f1SDimitry Andric unsigned NumErrorsBefore = Diags.getNumErrors(); 573fe6060f1SDimitry Andric 5745f757f3fSDimitry Andric LangOptions &LangOpts = Invocation.getLangOpts(); 575e8d8bef9SDimitry Andric CodeGenOptions &CodeGenOpts = Invocation.getCodeGenOpts(); 576e8d8bef9SDimitry Andric TargetOptions &TargetOpts = Invocation.getTargetOpts(); 577e8d8bef9SDimitry Andric FrontendOptions &FrontendOpts = Invocation.getFrontendOpts(); 578e8d8bef9SDimitry Andric CodeGenOpts.XRayInstrumentFunctions = LangOpts.XRayInstrument; 579e8d8bef9SDimitry Andric CodeGenOpts.XRayAlwaysEmitCustomEvents = LangOpts.XRayAlwaysEmitCustomEvents; 580e8d8bef9SDimitry Andric CodeGenOpts.XRayAlwaysEmitTypedEvents = LangOpts.XRayAlwaysEmitTypedEvents; 581e8d8bef9SDimitry Andric CodeGenOpts.DisableFree = FrontendOpts.DisableFree; 582e8d8bef9SDimitry Andric FrontendOpts.GenerateGlobalModuleIndex = FrontendOpts.UseGlobalModuleIndex; 583349cc55cSDimitry Andric if (FrontendOpts.ShowStats) 584349cc55cSDimitry Andric CodeGenOpts.ClearASTBeforeBackend = false; 585fe6060f1SDimitry Andric LangOpts.SanitizeCoverage = CodeGenOpts.hasSanitizeCoverage(); 586e8d8bef9SDimitry Andric LangOpts.ForceEmitVTables = CodeGenOpts.ForceEmitVTables; 587e8d8bef9SDimitry Andric LangOpts.SpeculativeLoadHardening = CodeGenOpts.SpeculativeLoadHardening; 588e8d8bef9SDimitry Andric LangOpts.CurrentModule = LangOpts.ModuleName; 589e8d8bef9SDimitry Andric 590e8d8bef9SDimitry Andric llvm::Triple T(TargetOpts.Triple); 591e8d8bef9SDimitry Andric llvm::Triple::ArchType Arch = T.getArch(); 592e8d8bef9SDimitry Andric 593e8d8bef9SDimitry Andric CodeGenOpts.CodeModel = TargetOpts.CodeModel; 5945f757f3fSDimitry Andric CodeGenOpts.LargeDataThreshold = TargetOpts.LargeDataThreshold; 595e8d8bef9SDimitry Andric 596fe6060f1SDimitry Andric if (LangOpts.getExceptionHandling() != 597fe6060f1SDimitry Andric LangOptions::ExceptionHandlingKind::None && 598e8d8bef9SDimitry Andric T.isWindowsMSVCEnvironment()) 599e8d8bef9SDimitry Andric Diags.Report(diag::err_fe_invalid_exception_model) 600e8d8bef9SDimitry Andric << static_cast<unsigned>(LangOpts.getExceptionHandling()) << T.str(); 601e8d8bef9SDimitry Andric 602e8d8bef9SDimitry Andric if (LangOpts.AppleKext && !LangOpts.CPlusPlus) 603e8d8bef9SDimitry Andric Diags.Report(diag::warn_c_kext); 604e8d8bef9SDimitry Andric 605e8d8bef9SDimitry Andric if (LangOpts.NewAlignOverride && 606e8d8bef9SDimitry Andric !llvm::isPowerOf2_32(LangOpts.NewAlignOverride)) { 607e8d8bef9SDimitry Andric Arg *A = Args.getLastArg(OPT_fnew_alignment_EQ); 608e8d8bef9SDimitry Andric Diags.Report(diag::err_fe_invalid_alignment) 609e8d8bef9SDimitry Andric << A->getAsString(Args) << A->getValue(); 610e8d8bef9SDimitry Andric LangOpts.NewAlignOverride = 0; 611e8d8bef9SDimitry Andric } 612e8d8bef9SDimitry Andric 6130fca6ea1SDimitry Andric // The -f[no-]raw-string-literals option is only valid in C and in C++ 6140fca6ea1SDimitry Andric // standards before C++11. 6150fca6ea1SDimitry Andric if (LangOpts.CPlusPlus11) { 6160fca6ea1SDimitry Andric if (Args.hasArg(OPT_fraw_string_literals, OPT_fno_raw_string_literals)) { 6170fca6ea1SDimitry Andric Args.claimAllArgs(OPT_fraw_string_literals, OPT_fno_raw_string_literals); 6180fca6ea1SDimitry Andric Diags.Report(diag::warn_drv_fraw_string_literals_in_cxx11) 6190fca6ea1SDimitry Andric << bool(LangOpts.RawStringLiterals); 6200fca6ea1SDimitry Andric } 6210fca6ea1SDimitry Andric 6220fca6ea1SDimitry Andric // Do not allow disabling raw string literals in C++11 or later. 6230fca6ea1SDimitry Andric LangOpts.RawStringLiterals = true; 6240fca6ea1SDimitry Andric } 6250fca6ea1SDimitry Andric 626fe6060f1SDimitry Andric // Prevent the user from specifying both -fsycl-is-device and -fsycl-is-host. 627fe6060f1SDimitry Andric if (LangOpts.SYCLIsDevice && LangOpts.SYCLIsHost) 628fe6060f1SDimitry Andric Diags.Report(diag::err_drv_argument_not_allowed_with) << "-fsycl-is-device" 629fe6060f1SDimitry Andric << "-fsycl-is-host"; 630fe6060f1SDimitry Andric 631e8d8bef9SDimitry Andric if (Args.hasArg(OPT_fgnu89_inline) && LangOpts.CPlusPlus) 632e8d8bef9SDimitry Andric Diags.Report(diag::err_drv_argument_not_allowed_with) 633e8d8bef9SDimitry Andric << "-fgnu89-inline" << GetInputKindName(IK); 634e8d8bef9SDimitry Andric 635bdd1243dSDimitry Andric if (Args.hasArg(OPT_hlsl_entrypoint) && !LangOpts.HLSL) 636bdd1243dSDimitry Andric Diags.Report(diag::err_drv_argument_not_allowed_with) 637bdd1243dSDimitry Andric << "-hlsl-entry" << GetInputKindName(IK); 638bdd1243dSDimitry Andric 639e8d8bef9SDimitry Andric if (Args.hasArg(OPT_fgpu_allow_device_init) && !LangOpts.HIP) 640e8d8bef9SDimitry Andric Diags.Report(diag::warn_ignored_hip_only_option) 641e8d8bef9SDimitry Andric << Args.getLastArg(OPT_fgpu_allow_device_init)->getAsString(Args); 642e8d8bef9SDimitry Andric 643e8d8bef9SDimitry Andric if (Args.hasArg(OPT_gpu_max_threads_per_block_EQ) && !LangOpts.HIP) 644e8d8bef9SDimitry Andric Diags.Report(diag::warn_ignored_hip_only_option) 645e8d8bef9SDimitry Andric << Args.getLastArg(OPT_gpu_max_threads_per_block_EQ)->getAsString(Args); 646e8d8bef9SDimitry Andric 64781ad6265SDimitry Andric // When these options are used, the compiler is allowed to apply 64881ad6265SDimitry Andric // optimizations that may affect the final result. For example 64981ad6265SDimitry Andric // (x+y)+z is transformed to x+(y+z) but may not give the same 65081ad6265SDimitry Andric // final result; it's not value safe. 65181ad6265SDimitry Andric // Another example can be to simplify x/x to 1.0 but x could be 0.0, INF 65281ad6265SDimitry Andric // or NaN. Final result may then differ. An error is issued when the eval 65381ad6265SDimitry Andric // method is set with one of these options. 65481ad6265SDimitry Andric if (Args.hasArg(OPT_ffp_eval_method_EQ)) { 65581ad6265SDimitry Andric if (LangOpts.ApproxFunc) 65681ad6265SDimitry Andric Diags.Report(diag::err_incompatible_fp_eval_method_options) << 0; 65781ad6265SDimitry Andric if (LangOpts.AllowFPReassoc) 65881ad6265SDimitry Andric Diags.Report(diag::err_incompatible_fp_eval_method_options) << 1; 65981ad6265SDimitry Andric if (LangOpts.AllowRecip) 66081ad6265SDimitry Andric Diags.Report(diag::err_incompatible_fp_eval_method_options) << 2; 66181ad6265SDimitry Andric } 66281ad6265SDimitry Andric 663e8d8bef9SDimitry Andric // -cl-strict-aliasing needs to emit diagnostic in the case where CL > 1.0. 664e8d8bef9SDimitry Andric // This option should be deprecated for CL > 1.0 because 665e8d8bef9SDimitry Andric // this option was added for compatibility with OpenCL 1.0. 666349cc55cSDimitry Andric if (Args.getLastArg(OPT_cl_strict_aliasing) && 667349cc55cSDimitry Andric (LangOpts.getOpenCLCompatibleVersion() > 100)) 668e8d8bef9SDimitry Andric Diags.Report(diag::warn_option_invalid_ocl_version) 669349cc55cSDimitry Andric << LangOpts.getOpenCLVersionString() 670e8d8bef9SDimitry Andric << Args.getLastArg(OPT_cl_strict_aliasing)->getAsString(Args); 671e8d8bef9SDimitry Andric 672e8d8bef9SDimitry Andric if (Arg *A = Args.getLastArg(OPT_fdefault_calling_conv_EQ)) { 673e8d8bef9SDimitry Andric auto DefaultCC = LangOpts.getDefaultCallingConv(); 674e8d8bef9SDimitry Andric 675e8d8bef9SDimitry Andric bool emitError = (DefaultCC == LangOptions::DCC_FastCall || 676e8d8bef9SDimitry Andric DefaultCC == LangOptions::DCC_StdCall) && 677e8d8bef9SDimitry Andric Arch != llvm::Triple::x86; 678e8d8bef9SDimitry Andric emitError |= (DefaultCC == LangOptions::DCC_VectorCall || 679e8d8bef9SDimitry Andric DefaultCC == LangOptions::DCC_RegCall) && 680e8d8bef9SDimitry Andric !T.isX86(); 6815f757f3fSDimitry Andric emitError |= DefaultCC == LangOptions::DCC_RtdCall && Arch != llvm::Triple::m68k; 682e8d8bef9SDimitry Andric if (emitError) 683e8d8bef9SDimitry Andric Diags.Report(diag::err_drv_argument_not_allowed_with) 684e8d8bef9SDimitry Andric << A->getSpelling() << T.getTriple(); 685e8d8bef9SDimitry Andric } 686e8d8bef9SDimitry Andric 687fe6060f1SDimitry Andric return Diags.getNumErrors() == NumErrorsBefore; 688e8d8bef9SDimitry Andric } 689e8d8bef9SDimitry Andric 6905ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 6910b57cec5SDimitry Andric // Deserialization (from args) 6920b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 6930b57cec5SDimitry Andric 6940b57cec5SDimitry Andric static unsigned getOptimizationLevel(ArgList &Args, InputKind IK, 6950b57cec5SDimitry Andric DiagnosticsEngine &Diags) { 6965f757f3fSDimitry Andric unsigned DefaultOpt = 0; 697fe6060f1SDimitry Andric if ((IK.getLanguage() == Language::OpenCL || 698fe6060f1SDimitry Andric IK.getLanguage() == Language::OpenCLCXX) && 699fe6060f1SDimitry Andric !Args.hasArg(OPT_cl_opt_disable)) 7005f757f3fSDimitry Andric DefaultOpt = 2; 7010b57cec5SDimitry Andric 7020b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { 7030b57cec5SDimitry Andric if (A->getOption().matches(options::OPT_O0)) 7045f757f3fSDimitry Andric return 0; 7050b57cec5SDimitry Andric 7060b57cec5SDimitry Andric if (A->getOption().matches(options::OPT_Ofast)) 7075f757f3fSDimitry Andric return 3; 7080b57cec5SDimitry Andric 7090b57cec5SDimitry Andric assert(A->getOption().matches(options::OPT_O)); 7100b57cec5SDimitry Andric 7110b57cec5SDimitry Andric StringRef S(A->getValue()); 7125ffd83dbSDimitry Andric if (S == "s" || S == "z") 7135f757f3fSDimitry Andric return 2; 7140b57cec5SDimitry Andric 7150b57cec5SDimitry Andric if (S == "g") 7165f757f3fSDimitry Andric return 1; 7170b57cec5SDimitry Andric 7180b57cec5SDimitry Andric return getLastArgIntValue(Args, OPT_O, DefaultOpt, Diags); 7190b57cec5SDimitry Andric } 7200b57cec5SDimitry Andric 7210b57cec5SDimitry Andric return DefaultOpt; 7220b57cec5SDimitry Andric } 7230b57cec5SDimitry Andric 7240b57cec5SDimitry Andric static unsigned getOptimizationLevelSize(ArgList &Args) { 7250b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { 7260b57cec5SDimitry Andric if (A->getOption().matches(options::OPT_O)) { 7270b57cec5SDimitry Andric switch (A->getValue()[0]) { 7280b57cec5SDimitry Andric default: 7290b57cec5SDimitry Andric return 0; 7300b57cec5SDimitry Andric case 's': 7310b57cec5SDimitry Andric return 1; 7320b57cec5SDimitry Andric case 'z': 7330b57cec5SDimitry Andric return 2; 7340b57cec5SDimitry Andric } 7350b57cec5SDimitry Andric } 7360b57cec5SDimitry Andric } 7370b57cec5SDimitry Andric return 0; 7380b57cec5SDimitry Andric } 7390b57cec5SDimitry Andric 7405f757f3fSDimitry Andric static void GenerateArg(ArgumentConsumer Consumer, 7415f757f3fSDimitry Andric llvm::opt::OptSpecifier OptSpecifier) { 742fe6060f1SDimitry Andric Option Opt = getDriverOptTable().getOption(OptSpecifier); 7435f757f3fSDimitry Andric denormalizeSimpleFlag(Consumer, Opt.getPrefixedName(), 744fe6060f1SDimitry Andric Option::OptionClass::FlagClass, 0); 745fe6060f1SDimitry Andric } 746fe6060f1SDimitry Andric 7475f757f3fSDimitry Andric static void GenerateArg(ArgumentConsumer Consumer, 748fe6060f1SDimitry Andric llvm::opt::OptSpecifier OptSpecifier, 7495f757f3fSDimitry Andric const Twine &Value) { 750fe6060f1SDimitry Andric Option Opt = getDriverOptTable().getOption(OptSpecifier); 7515f757f3fSDimitry Andric denormalizeString(Consumer, Opt.getPrefixedName(), Opt.getKind(), 0, Value); 752fe6060f1SDimitry Andric } 753fe6060f1SDimitry Andric 754fe6060f1SDimitry Andric // Parse command line arguments into CompilerInvocation. 755fe6060f1SDimitry Andric using ParseFn = 756fe6060f1SDimitry Andric llvm::function_ref<bool(CompilerInvocation &, ArrayRef<const char *>, 757fe6060f1SDimitry Andric DiagnosticsEngine &, const char *)>; 758fe6060f1SDimitry Andric 759fe6060f1SDimitry Andric // Generate command line arguments from CompilerInvocation. 760fe6060f1SDimitry Andric using GenerateFn = llvm::function_ref<void( 761fe6060f1SDimitry Andric CompilerInvocation &, SmallVectorImpl<const char *> &, 762fe6060f1SDimitry Andric CompilerInvocation::StringAllocator)>; 763fe6060f1SDimitry Andric 76406c3fb27SDimitry Andric /// May perform round-trip of command line arguments. By default, the round-trip 76506c3fb27SDimitry Andric /// is enabled in assert builds. This can be overwritten at run-time via the 76606c3fb27SDimitry Andric /// "-round-trip-args" and "-no-round-trip-args" command line flags, or via the 76706c3fb27SDimitry Andric /// ForceRoundTrip parameter. 76806c3fb27SDimitry Andric /// 76906c3fb27SDimitry Andric /// During round-trip, the command line arguments are parsed into a dummy 77006c3fb27SDimitry Andric /// CompilerInvocation, which is used to generate the command line arguments 77106c3fb27SDimitry Andric /// again. The real CompilerInvocation is then created by parsing the generated 77206c3fb27SDimitry Andric /// arguments, not the original ones. This (in combination with tests covering 77306c3fb27SDimitry Andric /// argument behavior) ensures the generated command line is complete (doesn't 77406c3fb27SDimitry Andric /// drop/mangle any arguments). 77506c3fb27SDimitry Andric /// 77606c3fb27SDimitry Andric /// Finally, we check the command line that was used to create the real 77706c3fb27SDimitry Andric /// CompilerInvocation instance. By default, we compare it to the command line 77806c3fb27SDimitry Andric /// the real CompilerInvocation generates. This checks whether the generator is 77906c3fb27SDimitry Andric /// deterministic. If \p CheckAgainstOriginalInvocation is enabled, we instead 78006c3fb27SDimitry Andric /// compare it to the original command line to verify the original command-line 78106c3fb27SDimitry Andric /// was canonical and can round-trip exactly. 782fe6060f1SDimitry Andric static bool RoundTrip(ParseFn Parse, GenerateFn Generate, 783fe6060f1SDimitry Andric CompilerInvocation &RealInvocation, 784fe6060f1SDimitry Andric CompilerInvocation &DummyInvocation, 785fe6060f1SDimitry Andric ArrayRef<const char *> CommandLineArgs, 78606c3fb27SDimitry Andric DiagnosticsEngine &Diags, const char *Argv0, 78706c3fb27SDimitry Andric bool CheckAgainstOriginalInvocation = false, 78806c3fb27SDimitry Andric bool ForceRoundTrip = false) { 789349cc55cSDimitry Andric #ifndef NDEBUG 790fe6060f1SDimitry Andric bool DoRoundTripDefault = true; 791fe6060f1SDimitry Andric #else 792fe6060f1SDimitry Andric bool DoRoundTripDefault = false; 793fe6060f1SDimitry Andric #endif 794fe6060f1SDimitry Andric 795fe6060f1SDimitry Andric bool DoRoundTrip = DoRoundTripDefault; 79606c3fb27SDimitry Andric if (ForceRoundTrip) { 79706c3fb27SDimitry Andric DoRoundTrip = true; 79806c3fb27SDimitry Andric } else { 799fe6060f1SDimitry Andric for (const auto *Arg : CommandLineArgs) { 800fe6060f1SDimitry Andric if (Arg == StringRef("-round-trip-args")) 801fe6060f1SDimitry Andric DoRoundTrip = true; 802fe6060f1SDimitry Andric if (Arg == StringRef("-no-round-trip-args")) 803fe6060f1SDimitry Andric DoRoundTrip = false; 804fe6060f1SDimitry Andric } 80506c3fb27SDimitry Andric } 806fe6060f1SDimitry Andric 807fe6060f1SDimitry Andric // If round-trip was not requested, simply run the parser with the real 808fe6060f1SDimitry Andric // invocation diagnostics. 809fe6060f1SDimitry Andric if (!DoRoundTrip) 810fe6060f1SDimitry Andric return Parse(RealInvocation, CommandLineArgs, Diags, Argv0); 811fe6060f1SDimitry Andric 812fe6060f1SDimitry Andric // Serializes quoted (and potentially escaped) arguments. 813fe6060f1SDimitry Andric auto SerializeArgs = [](ArrayRef<const char *> Args) { 814fe6060f1SDimitry Andric std::string Buffer; 815fe6060f1SDimitry Andric llvm::raw_string_ostream OS(Buffer); 816fe6060f1SDimitry Andric for (const char *Arg : Args) { 817fe6060f1SDimitry Andric llvm::sys::printArg(OS, Arg, /*Quote=*/true); 818fe6060f1SDimitry Andric OS << ' '; 819fe6060f1SDimitry Andric } 820fe6060f1SDimitry Andric OS.flush(); 821fe6060f1SDimitry Andric return Buffer; 822fe6060f1SDimitry Andric }; 823fe6060f1SDimitry Andric 824fe6060f1SDimitry Andric // Setup a dummy DiagnosticsEngine. 825fe6060f1SDimitry Andric DiagnosticsEngine DummyDiags(new DiagnosticIDs(), new DiagnosticOptions()); 826fe6060f1SDimitry Andric DummyDiags.setClient(new TextDiagnosticBuffer()); 827fe6060f1SDimitry Andric 828fe6060f1SDimitry Andric // Run the first parse on the original arguments with the dummy invocation and 829fe6060f1SDimitry Andric // diagnostics. 830fe6060f1SDimitry Andric if (!Parse(DummyInvocation, CommandLineArgs, DummyDiags, Argv0) || 831fe6060f1SDimitry Andric DummyDiags.getNumWarnings() != 0) { 832fe6060f1SDimitry Andric // If the first parse did not succeed, it must be user mistake (invalid 833fe6060f1SDimitry Andric // command line arguments). We won't be able to generate arguments that 834fe6060f1SDimitry Andric // would reproduce the same result. Let's fail again with the real 835fe6060f1SDimitry Andric // invocation and diagnostics, so all side-effects of parsing are visible. 836fe6060f1SDimitry Andric unsigned NumWarningsBefore = Diags.getNumWarnings(); 837fe6060f1SDimitry Andric auto Success = Parse(RealInvocation, CommandLineArgs, Diags, Argv0); 838fe6060f1SDimitry Andric if (!Success || Diags.getNumWarnings() != NumWarningsBefore) 839fe6060f1SDimitry Andric return Success; 840fe6060f1SDimitry Andric 841fe6060f1SDimitry Andric // Parse with original options and diagnostics succeeded even though it 842fe6060f1SDimitry Andric // shouldn't have. Something is off. 843fe6060f1SDimitry Andric Diags.Report(diag::err_cc1_round_trip_fail_then_ok); 844fe6060f1SDimitry Andric Diags.Report(diag::note_cc1_round_trip_original) 845fe6060f1SDimitry Andric << SerializeArgs(CommandLineArgs); 846fe6060f1SDimitry Andric return false; 847fe6060f1SDimitry Andric } 848fe6060f1SDimitry Andric 849fe6060f1SDimitry Andric // Setup string allocator. 850fe6060f1SDimitry Andric llvm::BumpPtrAllocator Alloc; 851fe6060f1SDimitry Andric llvm::StringSaver StringPool(Alloc); 852fe6060f1SDimitry Andric auto SA = [&StringPool](const Twine &Arg) { 853fe6060f1SDimitry Andric return StringPool.save(Arg).data(); 854fe6060f1SDimitry Andric }; 855fe6060f1SDimitry Andric 856fe6060f1SDimitry Andric // Generate arguments from the dummy invocation. If Generate is the 857fe6060f1SDimitry Andric // inverse of Parse, the newly generated arguments must have the same 858fe6060f1SDimitry Andric // semantics as the original. 85906c3fb27SDimitry Andric SmallVector<const char *> GeneratedArgs; 86006c3fb27SDimitry Andric Generate(DummyInvocation, GeneratedArgs, SA); 861fe6060f1SDimitry Andric 862fe6060f1SDimitry Andric // Run the second parse, now on the generated arguments, and with the real 863fe6060f1SDimitry Andric // invocation and diagnostics. The result is what we will end up using for the 864fe6060f1SDimitry Andric // rest of compilation, so if Generate is not inverse of Parse, something down 865fe6060f1SDimitry Andric // the line will break. 86606c3fb27SDimitry Andric bool Success2 = Parse(RealInvocation, GeneratedArgs, Diags, Argv0); 867fe6060f1SDimitry Andric 868fe6060f1SDimitry Andric // The first parse on original arguments succeeded, but second parse of 869fe6060f1SDimitry Andric // generated arguments failed. Something must be wrong with the generator. 870fe6060f1SDimitry Andric if (!Success2) { 871fe6060f1SDimitry Andric Diags.Report(diag::err_cc1_round_trip_ok_then_fail); 872fe6060f1SDimitry Andric Diags.Report(diag::note_cc1_round_trip_generated) 87306c3fb27SDimitry Andric << 1 << SerializeArgs(GeneratedArgs); 874fe6060f1SDimitry Andric return false; 875fe6060f1SDimitry Andric } 876fe6060f1SDimitry Andric 87706c3fb27SDimitry Andric SmallVector<const char *> ComparisonArgs; 87806c3fb27SDimitry Andric if (CheckAgainstOriginalInvocation) 87906c3fb27SDimitry Andric // Compare against original arguments. 88006c3fb27SDimitry Andric ComparisonArgs.assign(CommandLineArgs.begin(), CommandLineArgs.end()); 88106c3fb27SDimitry Andric else 882fe6060f1SDimitry Andric // Generate arguments again, this time from the options we will end up using 883fe6060f1SDimitry Andric // for the rest of the compilation. 88406c3fb27SDimitry Andric Generate(RealInvocation, ComparisonArgs, SA); 885fe6060f1SDimitry Andric 88606c3fb27SDimitry Andric // Compares two lists of arguments. 887fe6060f1SDimitry Andric auto Equal = [](const ArrayRef<const char *> A, 888fe6060f1SDimitry Andric const ArrayRef<const char *> B) { 889fe6060f1SDimitry Andric return std::equal(A.begin(), A.end(), B.begin(), B.end(), 890fe6060f1SDimitry Andric [](const char *AElem, const char *BElem) { 891fe6060f1SDimitry Andric return StringRef(AElem) == StringRef(BElem); 892fe6060f1SDimitry Andric }); 893fe6060f1SDimitry Andric }; 894fe6060f1SDimitry Andric 895fe6060f1SDimitry Andric // If we generated different arguments from what we assume are two 896fe6060f1SDimitry Andric // semantically equivalent CompilerInvocations, the Generate function may 897fe6060f1SDimitry Andric // be non-deterministic. 89806c3fb27SDimitry Andric if (!Equal(GeneratedArgs, ComparisonArgs)) { 899fe6060f1SDimitry Andric Diags.Report(diag::err_cc1_round_trip_mismatch); 900fe6060f1SDimitry Andric Diags.Report(diag::note_cc1_round_trip_generated) 90106c3fb27SDimitry Andric << 1 << SerializeArgs(GeneratedArgs); 902fe6060f1SDimitry Andric Diags.Report(diag::note_cc1_round_trip_generated) 90306c3fb27SDimitry Andric << 2 << SerializeArgs(ComparisonArgs); 904fe6060f1SDimitry Andric return false; 905fe6060f1SDimitry Andric } 906fe6060f1SDimitry Andric 907fe6060f1SDimitry Andric Diags.Report(diag::remark_cc1_round_trip_generated) 90806c3fb27SDimitry Andric << 1 << SerializeArgs(GeneratedArgs); 909fe6060f1SDimitry Andric Diags.Report(diag::remark_cc1_round_trip_generated) 91006c3fb27SDimitry Andric << 2 << SerializeArgs(ComparisonArgs); 911fe6060f1SDimitry Andric 912fe6060f1SDimitry Andric return Success2; 913e8d8bef9SDimitry Andric } 914e8d8bef9SDimitry Andric 91506c3fb27SDimitry Andric bool CompilerInvocation::checkCC1RoundTrip(ArrayRef<const char *> Args, 91606c3fb27SDimitry Andric DiagnosticsEngine &Diags, 91706c3fb27SDimitry Andric const char *Argv0) { 91806c3fb27SDimitry Andric CompilerInvocation DummyInvocation1, DummyInvocation2; 91906c3fb27SDimitry Andric return RoundTrip( 92006c3fb27SDimitry Andric [](CompilerInvocation &Invocation, ArrayRef<const char *> CommandLineArgs, 92106c3fb27SDimitry Andric DiagnosticsEngine &Diags, const char *Argv0) { 92206c3fb27SDimitry Andric return CreateFromArgsImpl(Invocation, CommandLineArgs, Diags, Argv0); 92306c3fb27SDimitry Andric }, 92406c3fb27SDimitry Andric [](CompilerInvocation &Invocation, SmallVectorImpl<const char *> &Args, 92506c3fb27SDimitry Andric StringAllocator SA) { 92606c3fb27SDimitry Andric Args.push_back("-cc1"); 92706c3fb27SDimitry Andric Invocation.generateCC1CommandLine(Args, SA); 92806c3fb27SDimitry Andric }, 92906c3fb27SDimitry Andric DummyInvocation1, DummyInvocation2, Args, Diags, Argv0, 93006c3fb27SDimitry Andric /*CheckAgainstOriginalInvocation=*/true, /*ForceRoundTrip=*/true); 93106c3fb27SDimitry Andric } 93206c3fb27SDimitry Andric 9330b57cec5SDimitry Andric static void addDiagnosticArgs(ArgList &Args, OptSpecifier Group, 9340b57cec5SDimitry Andric OptSpecifier GroupWithValue, 9350b57cec5SDimitry Andric std::vector<std::string> &Diagnostics) { 9360b57cec5SDimitry Andric for (auto *A : Args.filtered(Group)) { 9370b57cec5SDimitry Andric if (A->getOption().getKind() == Option::FlagClass) { 9380b57cec5SDimitry Andric // The argument is a pure flag (such as OPT_Wall or OPT_Wdeprecated). Add 939fe6060f1SDimitry Andric // its name (minus the "W" or "R" at the beginning) to the diagnostics. 9405ffd83dbSDimitry Andric Diagnostics.push_back( 9415ffd83dbSDimitry Andric std::string(A->getOption().getName().drop_front(1))); 9420b57cec5SDimitry Andric } else if (A->getOption().matches(GroupWithValue)) { 943fe6060f1SDimitry Andric // This is -Wfoo= or -Rfoo=, where foo is the name of the diagnostic 944fe6060f1SDimitry Andric // group. Add only the group name to the diagnostics. 9455ffd83dbSDimitry Andric Diagnostics.push_back( 9465ffd83dbSDimitry Andric std::string(A->getOption().getName().drop_front(1).rtrim("=-"))); 9470b57cec5SDimitry Andric } else { 9480b57cec5SDimitry Andric // Otherwise, add its value (for OPT_W_Joined and similar). 949fe6060f1SDimitry Andric Diagnostics.push_back(A->getValue()); 9500b57cec5SDimitry Andric } 9510b57cec5SDimitry Andric } 9520b57cec5SDimitry Andric } 9530b57cec5SDimitry Andric 9540b57cec5SDimitry Andric // Parse the Static Analyzer configuration. If \p Diags is set to nullptr, 9550b57cec5SDimitry Andric // it won't verify the input. 9560b57cec5SDimitry Andric static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts, 9570b57cec5SDimitry Andric DiagnosticsEngine *Diags); 9580b57cec5SDimitry Andric 9590b57cec5SDimitry Andric static void getAllNoBuiltinFuncValues(ArgList &Args, 9600b57cec5SDimitry Andric std::vector<std::string> &Funcs) { 961fe6060f1SDimitry Andric std::vector<std::string> Values = Args.getAllArgValues(OPT_fno_builtin_); 9620eae32dcSDimitry Andric auto BuiltinEnd = llvm::partition(Values, Builtin::Context::isBuiltinFunc); 963fe6060f1SDimitry Andric Funcs.insert(Funcs.end(), Values.begin(), BuiltinEnd); 964fe6060f1SDimitry Andric } 965fe6060f1SDimitry Andric 9665f757f3fSDimitry Andric static void GenerateAnalyzerArgs(const AnalyzerOptions &Opts, 9675f757f3fSDimitry Andric ArgumentConsumer Consumer) { 968fe6060f1SDimitry Andric const AnalyzerOptions *AnalyzerOpts = &Opts; 969fe6060f1SDimitry Andric 97006c3fb27SDimitry Andric #define ANALYZER_OPTION_WITH_MARSHALLING(...) \ 9715f757f3fSDimitry Andric GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__) 972fe6060f1SDimitry Andric #include "clang/Driver/Options.inc" 973fe6060f1SDimitry Andric #undef ANALYZER_OPTION_WITH_MARSHALLING 974fe6060f1SDimitry Andric 975fe6060f1SDimitry Andric if (Opts.AnalysisConstraintsOpt != RangeConstraintsModel) { 976fe6060f1SDimitry Andric switch (Opts.AnalysisConstraintsOpt) { 977fe6060f1SDimitry Andric #define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \ 978fe6060f1SDimitry Andric case NAME##Model: \ 9795f757f3fSDimitry Andric GenerateArg(Consumer, OPT_analyzer_constraints, CMDFLAG); \ 980fe6060f1SDimitry Andric break; 981fe6060f1SDimitry Andric #include "clang/StaticAnalyzer/Core/Analyses.def" 982fe6060f1SDimitry Andric default: 983fe6060f1SDimitry Andric llvm_unreachable("Tried to generate unknown analysis constraint."); 984fe6060f1SDimitry Andric } 985fe6060f1SDimitry Andric } 986fe6060f1SDimitry Andric 987fe6060f1SDimitry Andric if (Opts.AnalysisDiagOpt != PD_HTML) { 988fe6060f1SDimitry Andric switch (Opts.AnalysisDiagOpt) { 989fe6060f1SDimitry Andric #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) \ 990fe6060f1SDimitry Andric case PD_##NAME: \ 9915f757f3fSDimitry Andric GenerateArg(Consumer, OPT_analyzer_output, CMDFLAG); \ 992fe6060f1SDimitry Andric break; 993fe6060f1SDimitry Andric #include "clang/StaticAnalyzer/Core/Analyses.def" 994fe6060f1SDimitry Andric default: 995fe6060f1SDimitry Andric llvm_unreachable("Tried to generate unknown analysis diagnostic client."); 996fe6060f1SDimitry Andric } 997fe6060f1SDimitry Andric } 998fe6060f1SDimitry Andric 999fe6060f1SDimitry Andric if (Opts.AnalysisPurgeOpt != PurgeStmt) { 1000fe6060f1SDimitry Andric switch (Opts.AnalysisPurgeOpt) { 1001fe6060f1SDimitry Andric #define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) \ 1002fe6060f1SDimitry Andric case NAME: \ 10035f757f3fSDimitry Andric GenerateArg(Consumer, OPT_analyzer_purge, CMDFLAG); \ 1004fe6060f1SDimitry Andric break; 1005fe6060f1SDimitry Andric #include "clang/StaticAnalyzer/Core/Analyses.def" 1006fe6060f1SDimitry Andric default: 1007fe6060f1SDimitry Andric llvm_unreachable("Tried to generate unknown analysis purge mode."); 1008fe6060f1SDimitry Andric } 1009fe6060f1SDimitry Andric } 1010fe6060f1SDimitry Andric 1011fe6060f1SDimitry Andric if (Opts.InliningMode != NoRedundancy) { 1012fe6060f1SDimitry Andric switch (Opts.InliningMode) { 1013fe6060f1SDimitry Andric #define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) \ 1014fe6060f1SDimitry Andric case NAME: \ 10155f757f3fSDimitry Andric GenerateArg(Consumer, OPT_analyzer_inlining_mode, CMDFLAG); \ 1016fe6060f1SDimitry Andric break; 1017fe6060f1SDimitry Andric #include "clang/StaticAnalyzer/Core/Analyses.def" 1018fe6060f1SDimitry Andric default: 1019fe6060f1SDimitry Andric llvm_unreachable("Tried to generate unknown analysis inlining mode."); 1020fe6060f1SDimitry Andric } 1021fe6060f1SDimitry Andric } 1022fe6060f1SDimitry Andric 1023fe6060f1SDimitry Andric for (const auto &CP : Opts.CheckersAndPackages) { 1024fe6060f1SDimitry Andric OptSpecifier Opt = 1025fe6060f1SDimitry Andric CP.second ? OPT_analyzer_checker : OPT_analyzer_disable_checker; 10265f757f3fSDimitry Andric GenerateArg(Consumer, Opt, CP.first); 1027fe6060f1SDimitry Andric } 1028fe6060f1SDimitry Andric 1029fe6060f1SDimitry Andric AnalyzerOptions ConfigOpts; 1030fe6060f1SDimitry Andric parseAnalyzerConfigs(ConfigOpts, nullptr); 1031fe6060f1SDimitry Andric 103206c3fb27SDimitry Andric // Sort options by key to avoid relying on StringMap iteration order. 103306c3fb27SDimitry Andric SmallVector<std::pair<StringRef, StringRef>, 4> SortedConfigOpts; 103406c3fb27SDimitry Andric for (const auto &C : Opts.Config) 103506c3fb27SDimitry Andric SortedConfigOpts.emplace_back(C.getKey(), C.getValue()); 103606c3fb27SDimitry Andric llvm::sort(SortedConfigOpts, llvm::less_first()); 103706c3fb27SDimitry Andric 103806c3fb27SDimitry Andric for (const auto &[Key, Value] : SortedConfigOpts) { 1039fe6060f1SDimitry Andric // Don't generate anything that came from parseAnalyzerConfigs. It would be 1040fe6060f1SDimitry Andric // redundant and may not be valid on the command line. 104106c3fb27SDimitry Andric auto Entry = ConfigOpts.Config.find(Key); 104206c3fb27SDimitry Andric if (Entry != ConfigOpts.Config.end() && Entry->getValue() == Value) 1043fe6060f1SDimitry Andric continue; 1044fe6060f1SDimitry Andric 10455f757f3fSDimitry Andric GenerateArg(Consumer, OPT_analyzer_config, Key + "=" + Value); 1046fe6060f1SDimitry Andric } 1047fe6060f1SDimitry Andric 1048fe6060f1SDimitry Andric // Nothing to generate for FullCompilerInvocation. 10490b57cec5SDimitry Andric } 10500b57cec5SDimitry Andric 10510b57cec5SDimitry Andric static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, 10520b57cec5SDimitry Andric DiagnosticsEngine &Diags) { 1053fe6060f1SDimitry Andric unsigned NumErrorsBefore = Diags.getNumErrors(); 1054fe6060f1SDimitry Andric 1055fe6060f1SDimitry Andric AnalyzerOptions *AnalyzerOpts = &Opts; 1056fe6060f1SDimitry Andric 105706c3fb27SDimitry Andric #define ANALYZER_OPTION_WITH_MARSHALLING(...) \ 105806c3fb27SDimitry Andric PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__) 1059fe6060f1SDimitry Andric #include "clang/Driver/Options.inc" 1060fe6060f1SDimitry Andric #undef ANALYZER_OPTION_WITH_MARSHALLING 1061fe6060f1SDimitry Andric 10620b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(OPT_analyzer_constraints)) { 10630b57cec5SDimitry Andric StringRef Name = A->getValue(); 10640b57cec5SDimitry Andric AnalysisConstraints Value = llvm::StringSwitch<AnalysisConstraints>(Name) 10650b57cec5SDimitry Andric #define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \ 10660b57cec5SDimitry Andric .Case(CMDFLAG, NAME##Model) 10670b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/Analyses.def" 10680b57cec5SDimitry Andric .Default(NumConstraints); 10690b57cec5SDimitry Andric if (Value == NumConstraints) { 10700b57cec5SDimitry Andric Diags.Report(diag::err_drv_invalid_value) 10710b57cec5SDimitry Andric << A->getAsString(Args) << Name; 10720b57cec5SDimitry Andric } else { 107381ad6265SDimitry Andric #ifndef LLVM_WITH_Z3 107481ad6265SDimitry Andric if (Value == AnalysisConstraints::Z3ConstraintsModel) { 107581ad6265SDimitry Andric Diags.Report(diag::err_analyzer_not_built_with_z3); 107681ad6265SDimitry Andric } 107781ad6265SDimitry Andric #endif // LLVM_WITH_Z3 10780b57cec5SDimitry Andric Opts.AnalysisConstraintsOpt = Value; 10790b57cec5SDimitry Andric } 10800b57cec5SDimitry Andric } 10810b57cec5SDimitry Andric 10820b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(OPT_analyzer_output)) { 10830b57cec5SDimitry Andric StringRef Name = A->getValue(); 10840b57cec5SDimitry Andric AnalysisDiagClients Value = llvm::StringSwitch<AnalysisDiagClients>(Name) 10850b57cec5SDimitry Andric #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) \ 10860b57cec5SDimitry Andric .Case(CMDFLAG, PD_##NAME) 10870b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/Analyses.def" 10880b57cec5SDimitry Andric .Default(NUM_ANALYSIS_DIAG_CLIENTS); 10890b57cec5SDimitry Andric if (Value == NUM_ANALYSIS_DIAG_CLIENTS) { 10900b57cec5SDimitry Andric Diags.Report(diag::err_drv_invalid_value) 10910b57cec5SDimitry Andric << A->getAsString(Args) << Name; 10920b57cec5SDimitry Andric } else { 10930b57cec5SDimitry Andric Opts.AnalysisDiagOpt = Value; 10940b57cec5SDimitry Andric } 10950b57cec5SDimitry Andric } 10960b57cec5SDimitry Andric 10970b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(OPT_analyzer_purge)) { 10980b57cec5SDimitry Andric StringRef Name = A->getValue(); 10990b57cec5SDimitry Andric AnalysisPurgeMode Value = llvm::StringSwitch<AnalysisPurgeMode>(Name) 11000b57cec5SDimitry Andric #define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) \ 11010b57cec5SDimitry Andric .Case(CMDFLAG, NAME) 11020b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/Analyses.def" 11030b57cec5SDimitry Andric .Default(NumPurgeModes); 11040b57cec5SDimitry Andric if (Value == NumPurgeModes) { 11050b57cec5SDimitry Andric Diags.Report(diag::err_drv_invalid_value) 11060b57cec5SDimitry Andric << A->getAsString(Args) << Name; 11070b57cec5SDimitry Andric } else { 11080b57cec5SDimitry Andric Opts.AnalysisPurgeOpt = Value; 11090b57cec5SDimitry Andric } 11100b57cec5SDimitry Andric } 11110b57cec5SDimitry Andric 11120b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(OPT_analyzer_inlining_mode)) { 11130b57cec5SDimitry Andric StringRef Name = A->getValue(); 11140b57cec5SDimitry Andric AnalysisInliningMode Value = llvm::StringSwitch<AnalysisInliningMode>(Name) 11150b57cec5SDimitry Andric #define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) \ 11160b57cec5SDimitry Andric .Case(CMDFLAG, NAME) 11170b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/Analyses.def" 11180b57cec5SDimitry Andric .Default(NumInliningModes); 11190b57cec5SDimitry Andric if (Value == NumInliningModes) { 11200b57cec5SDimitry Andric Diags.Report(diag::err_drv_invalid_value) 11210b57cec5SDimitry Andric << A->getAsString(Args) << Name; 11220b57cec5SDimitry Andric } else { 11230b57cec5SDimitry Andric Opts.InliningMode = Value; 11240b57cec5SDimitry Andric } 11250b57cec5SDimitry Andric } 11260b57cec5SDimitry Andric 1127a7dea167SDimitry Andric Opts.CheckersAndPackages.clear(); 11280b57cec5SDimitry Andric for (const Arg *A : 11290b57cec5SDimitry Andric Args.filtered(OPT_analyzer_checker, OPT_analyzer_disable_checker)) { 11300b57cec5SDimitry Andric A->claim(); 1131a7dea167SDimitry Andric bool IsEnabled = A->getOption().getID() == OPT_analyzer_checker; 11320b57cec5SDimitry Andric // We can have a list of comma separated checker names, e.g: 11330b57cec5SDimitry Andric // '-analyzer-checker=cocoa,unix' 1134a7dea167SDimitry Andric StringRef CheckerAndPackageList = A->getValue(); 1135a7dea167SDimitry Andric SmallVector<StringRef, 16> CheckersAndPackages; 1136a7dea167SDimitry Andric CheckerAndPackageList.split(CheckersAndPackages, ","); 1137480093f4SDimitry Andric for (const StringRef &CheckerOrPackage : CheckersAndPackages) 11385ffd83dbSDimitry Andric Opts.CheckersAndPackages.emplace_back(std::string(CheckerOrPackage), 11395ffd83dbSDimitry Andric IsEnabled); 11400b57cec5SDimitry Andric } 11410b57cec5SDimitry Andric 11420b57cec5SDimitry Andric // Go through the analyzer configuration options. 11430b57cec5SDimitry Andric for (const auto *A : Args.filtered(OPT_analyzer_config)) { 11440b57cec5SDimitry Andric 11450b57cec5SDimitry Andric // We can have a list of comma separated config names, e.g: 11460b57cec5SDimitry Andric // '-analyzer-config key1=val1,key2=val2' 11470b57cec5SDimitry Andric StringRef configList = A->getValue(); 11480b57cec5SDimitry Andric SmallVector<StringRef, 4> configVals; 11490b57cec5SDimitry Andric configList.split(configVals, ","); 11500b57cec5SDimitry Andric for (const auto &configVal : configVals) { 11510b57cec5SDimitry Andric StringRef key, val; 11520b57cec5SDimitry Andric std::tie(key, val) = configVal.split("="); 11530b57cec5SDimitry Andric if (val.empty()) { 11540b57cec5SDimitry Andric Diags.Report(SourceLocation(), 11550b57cec5SDimitry Andric diag::err_analyzer_config_no_value) << configVal; 11560b57cec5SDimitry Andric break; 11570b57cec5SDimitry Andric } 1158349cc55cSDimitry Andric if (val.contains('=')) { 11590b57cec5SDimitry Andric Diags.Report(SourceLocation(), 11600b57cec5SDimitry Andric diag::err_analyzer_config_multiple_values) 11610b57cec5SDimitry Andric << configVal; 11620b57cec5SDimitry Andric break; 11630b57cec5SDimitry Andric } 11640b57cec5SDimitry Andric 11650b57cec5SDimitry Andric // TODO: Check checker options too, possibly in CheckerRegistry. 11660b57cec5SDimitry Andric // Leave unknown non-checker configs unclaimed. 11670b57cec5SDimitry Andric if (!key.contains(":") && Opts.isUnknownAnalyzerConfig(key)) { 11680b57cec5SDimitry Andric if (Opts.ShouldEmitErrorsOnInvalidConfigValue) 11690b57cec5SDimitry Andric Diags.Report(diag::err_analyzer_config_unknown) << key; 11700b57cec5SDimitry Andric continue; 11710b57cec5SDimitry Andric } 11720b57cec5SDimitry Andric 11730b57cec5SDimitry Andric A->claim(); 11745ffd83dbSDimitry Andric Opts.Config[key] = std::string(val); 11750b57cec5SDimitry Andric } 11760b57cec5SDimitry Andric } 11770b57cec5SDimitry Andric 11780b57cec5SDimitry Andric if (Opts.ShouldEmitErrorsOnInvalidConfigValue) 11790b57cec5SDimitry Andric parseAnalyzerConfigs(Opts, &Diags); 11800b57cec5SDimitry Andric else 11810b57cec5SDimitry Andric parseAnalyzerConfigs(Opts, nullptr); 11820b57cec5SDimitry Andric 11830b57cec5SDimitry Andric llvm::raw_string_ostream os(Opts.FullCompilerInvocation); 11840b57cec5SDimitry Andric for (unsigned i = 0; i < Args.getNumInputArgStrings(); ++i) { 11850b57cec5SDimitry Andric if (i != 0) 11860b57cec5SDimitry Andric os << " "; 11870b57cec5SDimitry Andric os << Args.getArgString(i); 11880b57cec5SDimitry Andric } 11890b57cec5SDimitry Andric os.flush(); 11900b57cec5SDimitry Andric 1191fe6060f1SDimitry Andric return Diags.getNumErrors() == NumErrorsBefore; 11920b57cec5SDimitry Andric } 11930b57cec5SDimitry Andric 11940b57cec5SDimitry Andric static StringRef getStringOption(AnalyzerOptions::ConfigTable &Config, 11950b57cec5SDimitry Andric StringRef OptionName, StringRef DefaultVal) { 11965ffd83dbSDimitry Andric return Config.insert({OptionName, std::string(DefaultVal)}).first->second; 11970b57cec5SDimitry Andric } 11980b57cec5SDimitry Andric 11990b57cec5SDimitry Andric static void initOption(AnalyzerOptions::ConfigTable &Config, 12000b57cec5SDimitry Andric DiagnosticsEngine *Diags, 12010b57cec5SDimitry Andric StringRef &OptionField, StringRef Name, 12020b57cec5SDimitry Andric StringRef DefaultVal) { 12030b57cec5SDimitry Andric // String options may be known to invalid (e.g. if the expected string is a 12040b57cec5SDimitry Andric // file name, but the file does not exist), those will have to be checked in 12050b57cec5SDimitry Andric // parseConfigs. 12060b57cec5SDimitry Andric OptionField = getStringOption(Config, Name, DefaultVal); 12070b57cec5SDimitry Andric } 12080b57cec5SDimitry Andric 12090b57cec5SDimitry Andric static void initOption(AnalyzerOptions::ConfigTable &Config, 12100b57cec5SDimitry Andric DiagnosticsEngine *Diags, 12110b57cec5SDimitry Andric bool &OptionField, StringRef Name, bool DefaultVal) { 1212bdd1243dSDimitry Andric auto PossiblyInvalidVal = 1213bdd1243dSDimitry Andric llvm::StringSwitch<std::optional<bool>>( 12140b57cec5SDimitry Andric getStringOption(Config, Name, (DefaultVal ? "true" : "false"))) 12150b57cec5SDimitry Andric .Case("true", true) 12160b57cec5SDimitry Andric .Case("false", false) 1217bdd1243dSDimitry Andric .Default(std::nullopt); 12180b57cec5SDimitry Andric 12190b57cec5SDimitry Andric if (!PossiblyInvalidVal) { 12200b57cec5SDimitry Andric if (Diags) 12210b57cec5SDimitry Andric Diags->Report(diag::err_analyzer_config_invalid_input) 12220b57cec5SDimitry Andric << Name << "a boolean"; 12230b57cec5SDimitry Andric else 12240b57cec5SDimitry Andric OptionField = DefaultVal; 12250b57cec5SDimitry Andric } else 122681ad6265SDimitry Andric OptionField = *PossiblyInvalidVal; 12270b57cec5SDimitry Andric } 12280b57cec5SDimitry Andric 12290b57cec5SDimitry Andric static void initOption(AnalyzerOptions::ConfigTable &Config, 12300b57cec5SDimitry Andric DiagnosticsEngine *Diags, 12310b57cec5SDimitry Andric unsigned &OptionField, StringRef Name, 12320b57cec5SDimitry Andric unsigned DefaultVal) { 12330b57cec5SDimitry Andric 12340b57cec5SDimitry Andric OptionField = DefaultVal; 12350b57cec5SDimitry Andric bool HasFailed = getStringOption(Config, Name, std::to_string(DefaultVal)) 12360b57cec5SDimitry Andric .getAsInteger(0, OptionField); 12370b57cec5SDimitry Andric if (Diags && HasFailed) 12380b57cec5SDimitry Andric Diags->Report(diag::err_analyzer_config_invalid_input) 12390b57cec5SDimitry Andric << Name << "an unsigned"; 12400b57cec5SDimitry Andric } 12410b57cec5SDimitry Andric 12420b57cec5SDimitry Andric static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts, 12430b57cec5SDimitry Andric DiagnosticsEngine *Diags) { 12440b57cec5SDimitry Andric // TODO: There's no need to store the entire configtable, it'd be plenty 12450b57cec5SDimitry Andric // enough to store checker options. 12460b57cec5SDimitry Andric 12470b57cec5SDimitry Andric #define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL) \ 12480b57cec5SDimitry Andric initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG, DEFAULT_VAL); 124981ad6265SDimitry Andric #define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(...) 125081ad6265SDimitry Andric #include "clang/StaticAnalyzer/Core/AnalyzerOptions.def" 12510b57cec5SDimitry Andric 125281ad6265SDimitry Andric assert(AnOpts.UserMode == "shallow" || AnOpts.UserMode == "deep"); 125381ad6265SDimitry Andric const bool InShallowMode = AnOpts.UserMode == "shallow"; 125481ad6265SDimitry Andric 125581ad6265SDimitry Andric #define ANALYZER_OPTION(...) 12560b57cec5SDimitry Andric #define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \ 12570b57cec5SDimitry Andric SHALLOW_VAL, DEEP_VAL) \ 125881ad6265SDimitry Andric initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG, \ 125981ad6265SDimitry Andric InShallowMode ? SHALLOW_VAL : DEEP_VAL); 12600b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/AnalyzerOptions.def" 12610b57cec5SDimitry Andric 12620b57cec5SDimitry Andric // At this point, AnalyzerOptions is configured. Let's validate some options. 12630b57cec5SDimitry Andric 1264a7dea167SDimitry Andric // FIXME: Here we try to validate the silenced checkers or packages are valid. 1265a7dea167SDimitry Andric // The current approach only validates the registered checkers which does not 1266a7dea167SDimitry Andric // contain the runtime enabled checkers and optimally we would validate both. 1267a7dea167SDimitry Andric if (!AnOpts.RawSilencedCheckersAndPackages.empty()) { 1268a7dea167SDimitry Andric std::vector<StringRef> Checkers = 1269a7dea167SDimitry Andric AnOpts.getRegisteredCheckers(/*IncludeExperimental=*/true); 1270a7dea167SDimitry Andric std::vector<StringRef> Packages = 1271a7dea167SDimitry Andric AnOpts.getRegisteredPackages(/*IncludeExperimental=*/true); 1272a7dea167SDimitry Andric 1273a7dea167SDimitry Andric SmallVector<StringRef, 16> CheckersAndPackages; 1274a7dea167SDimitry Andric AnOpts.RawSilencedCheckersAndPackages.split(CheckersAndPackages, ";"); 1275a7dea167SDimitry Andric 1276480093f4SDimitry Andric for (const StringRef &CheckerOrPackage : CheckersAndPackages) { 1277a7dea167SDimitry Andric if (Diags) { 1278a7dea167SDimitry Andric bool IsChecker = CheckerOrPackage.contains('.'); 1279349cc55cSDimitry Andric bool IsValidName = IsChecker 1280349cc55cSDimitry Andric ? llvm::is_contained(Checkers, CheckerOrPackage) 1281349cc55cSDimitry Andric : llvm::is_contained(Packages, CheckerOrPackage); 1282a7dea167SDimitry Andric 1283a7dea167SDimitry Andric if (!IsValidName) 1284a7dea167SDimitry Andric Diags->Report(diag::err_unknown_analyzer_checker_or_package) 1285a7dea167SDimitry Andric << CheckerOrPackage; 1286a7dea167SDimitry Andric } 1287a7dea167SDimitry Andric 1288a7dea167SDimitry Andric AnOpts.SilencedCheckersAndPackages.emplace_back(CheckerOrPackage); 1289a7dea167SDimitry Andric } 1290a7dea167SDimitry Andric } 1291a7dea167SDimitry Andric 12920b57cec5SDimitry Andric if (!Diags) 12930b57cec5SDimitry Andric return; 12940b57cec5SDimitry Andric 12950b57cec5SDimitry Andric if (AnOpts.ShouldTrackConditionsDebug && !AnOpts.ShouldTrackConditions) 12960b57cec5SDimitry Andric Diags->Report(diag::err_analyzer_config_invalid_input) 12970b57cec5SDimitry Andric << "track-conditions-debug" << "'track-conditions' to also be enabled"; 12980b57cec5SDimitry Andric 12990b57cec5SDimitry Andric if (!AnOpts.CTUDir.empty() && !llvm::sys::fs::is_directory(AnOpts.CTUDir)) 13000b57cec5SDimitry Andric Diags->Report(diag::err_analyzer_config_invalid_input) << "ctu-dir" 13010b57cec5SDimitry Andric << "a filename"; 13020b57cec5SDimitry Andric 13030b57cec5SDimitry Andric if (!AnOpts.ModelPath.empty() && 13040b57cec5SDimitry Andric !llvm::sys::fs::is_directory(AnOpts.ModelPath)) 13050b57cec5SDimitry Andric Diags->Report(diag::err_analyzer_config_invalid_input) << "model-path" 13060b57cec5SDimitry Andric << "a filename"; 13070b57cec5SDimitry Andric } 13080b57cec5SDimitry Andric 1309fe6060f1SDimitry Andric /// Generate a remark argument. This is an inverse of `ParseOptimizationRemark`. 1310fe6060f1SDimitry Andric static void 13115f757f3fSDimitry Andric GenerateOptimizationRemark(ArgumentConsumer Consumer, OptSpecifier OptEQ, 13125f757f3fSDimitry Andric StringRef Name, 1313fe6060f1SDimitry Andric const CodeGenOptions::OptRemark &Remark) { 1314fe6060f1SDimitry Andric if (Remark.hasValidPattern()) { 13155f757f3fSDimitry Andric GenerateArg(Consumer, OptEQ, Remark.Pattern); 1316fe6060f1SDimitry Andric } else if (Remark.Kind == CodeGenOptions::RK_Enabled) { 13175f757f3fSDimitry Andric GenerateArg(Consumer, OPT_R_Joined, Name); 1318fe6060f1SDimitry Andric } else if (Remark.Kind == CodeGenOptions::RK_Disabled) { 13195f757f3fSDimitry Andric GenerateArg(Consumer, OPT_R_Joined, StringRef("no-") + Name); 13200b57cec5SDimitry Andric } 1321fe6060f1SDimitry Andric } 1322fe6060f1SDimitry Andric 1323fe6060f1SDimitry Andric /// Parse a remark command line argument. It may be missing, disabled/enabled by 1324fe6060f1SDimitry Andric /// '-R[no-]group' or specified with a regular expression by '-Rgroup=regexp'. 1325fe6060f1SDimitry Andric /// On top of that, it can be disabled/enabled globally by '-R[no-]everything'. 1326fe6060f1SDimitry Andric static CodeGenOptions::OptRemark 1327fe6060f1SDimitry Andric ParseOptimizationRemark(DiagnosticsEngine &Diags, ArgList &Args, 1328fe6060f1SDimitry Andric OptSpecifier OptEQ, StringRef Name) { 1329fe6060f1SDimitry Andric CodeGenOptions::OptRemark Result; 1330fe6060f1SDimitry Andric 1331349cc55cSDimitry Andric auto InitializeResultPattern = [&Diags, &Args, &Result](const Arg *A, 1332349cc55cSDimitry Andric StringRef Pattern) { 1333349cc55cSDimitry Andric Result.Pattern = Pattern.str(); 1334fe6060f1SDimitry Andric 1335fe6060f1SDimitry Andric std::string RegexError; 1336fe6060f1SDimitry Andric Result.Regex = std::make_shared<llvm::Regex>(Result.Pattern); 1337fe6060f1SDimitry Andric if (!Result.Regex->isValid(RegexError)) { 1338fe6060f1SDimitry Andric Diags.Report(diag::err_drv_optimization_remark_pattern) 1339fe6060f1SDimitry Andric << RegexError << A->getAsString(Args); 1340fe6060f1SDimitry Andric return false; 1341fe6060f1SDimitry Andric } 1342fe6060f1SDimitry Andric 1343fe6060f1SDimitry Andric return true; 1344fe6060f1SDimitry Andric }; 1345fe6060f1SDimitry Andric 1346fe6060f1SDimitry Andric for (Arg *A : Args) { 1347fe6060f1SDimitry Andric if (A->getOption().matches(OPT_R_Joined)) { 1348fe6060f1SDimitry Andric StringRef Value = A->getValue(); 1349fe6060f1SDimitry Andric 1350fe6060f1SDimitry Andric if (Value == Name) 1351fe6060f1SDimitry Andric Result.Kind = CodeGenOptions::RK_Enabled; 1352fe6060f1SDimitry Andric else if (Value == "everything") 1353fe6060f1SDimitry Andric Result.Kind = CodeGenOptions::RK_EnabledEverything; 1354fe6060f1SDimitry Andric else if (Value.split('-') == std::make_pair(StringRef("no"), Name)) 1355fe6060f1SDimitry Andric Result.Kind = CodeGenOptions::RK_Disabled; 1356fe6060f1SDimitry Andric else if (Value == "no-everything") 1357fe6060f1SDimitry Andric Result.Kind = CodeGenOptions::RK_DisabledEverything; 1358349cc55cSDimitry Andric else 1359349cc55cSDimitry Andric continue; 1360fe6060f1SDimitry Andric 1361fe6060f1SDimitry Andric if (Result.Kind == CodeGenOptions::RK_Disabled || 1362fe6060f1SDimitry Andric Result.Kind == CodeGenOptions::RK_DisabledEverything) { 1363fe6060f1SDimitry Andric Result.Pattern = ""; 1364fe6060f1SDimitry Andric Result.Regex = nullptr; 1365349cc55cSDimitry Andric } else { 1366349cc55cSDimitry Andric InitializeResultPattern(A, ".*"); 1367349cc55cSDimitry Andric } 1368349cc55cSDimitry Andric } else if (A->getOption().matches(OptEQ)) { 1369349cc55cSDimitry Andric Result.Kind = CodeGenOptions::RK_WithPattern; 1370349cc55cSDimitry Andric if (!InitializeResultPattern(A, A->getValue())) 1371349cc55cSDimitry Andric return CodeGenOptions::OptRemark(); 1372349cc55cSDimitry Andric } 1373fe6060f1SDimitry Andric } 1374fe6060f1SDimitry Andric 1375fe6060f1SDimitry Andric return Result; 13760b57cec5SDimitry Andric } 13770b57cec5SDimitry Andric 13780b57cec5SDimitry Andric static bool parseDiagnosticLevelMask(StringRef FlagName, 13790b57cec5SDimitry Andric const std::vector<std::string> &Levels, 1380e8d8bef9SDimitry Andric DiagnosticsEngine &Diags, 13810b57cec5SDimitry Andric DiagnosticLevelMask &M) { 13820b57cec5SDimitry Andric bool Success = true; 13830b57cec5SDimitry Andric for (const auto &Level : Levels) { 13840b57cec5SDimitry Andric DiagnosticLevelMask const PM = 13850b57cec5SDimitry Andric llvm::StringSwitch<DiagnosticLevelMask>(Level) 13860b57cec5SDimitry Andric .Case("note", DiagnosticLevelMask::Note) 13870b57cec5SDimitry Andric .Case("remark", DiagnosticLevelMask::Remark) 13880b57cec5SDimitry Andric .Case("warning", DiagnosticLevelMask::Warning) 13890b57cec5SDimitry Andric .Case("error", DiagnosticLevelMask::Error) 13900b57cec5SDimitry Andric .Default(DiagnosticLevelMask::None); 13910b57cec5SDimitry Andric if (PM == DiagnosticLevelMask::None) { 13920b57cec5SDimitry Andric Success = false; 1393e8d8bef9SDimitry Andric Diags.Report(diag::err_drv_invalid_value) << FlagName << Level; 13940b57cec5SDimitry Andric } 13950b57cec5SDimitry Andric M = M | PM; 13960b57cec5SDimitry Andric } 13970b57cec5SDimitry Andric return Success; 13980b57cec5SDimitry Andric } 13990b57cec5SDimitry Andric 14000b57cec5SDimitry Andric static void parseSanitizerKinds(StringRef FlagName, 14010b57cec5SDimitry Andric const std::vector<std::string> &Sanitizers, 14020b57cec5SDimitry Andric DiagnosticsEngine &Diags, SanitizerSet &S) { 14030b57cec5SDimitry Andric for (const auto &Sanitizer : Sanitizers) { 14040b57cec5SDimitry Andric SanitizerMask K = parseSanitizerValue(Sanitizer, /*AllowGroups=*/false); 14050b57cec5SDimitry Andric if (K == SanitizerMask()) 14060b57cec5SDimitry Andric Diags.Report(diag::err_drv_invalid_value) << FlagName << Sanitizer; 14070b57cec5SDimitry Andric else 14080b57cec5SDimitry Andric S.set(K, true); 14090b57cec5SDimitry Andric } 14100b57cec5SDimitry Andric } 14110b57cec5SDimitry Andric 1412fe6060f1SDimitry Andric static SmallVector<StringRef, 4> serializeSanitizerKinds(SanitizerSet S) { 1413fe6060f1SDimitry Andric SmallVector<StringRef, 4> Values; 1414fe6060f1SDimitry Andric serializeSanitizerSet(S, Values); 1415fe6060f1SDimitry Andric return Values; 1416fe6060f1SDimitry Andric } 1417fe6060f1SDimitry Andric 14180b57cec5SDimitry Andric static void parseXRayInstrumentationBundle(StringRef FlagName, StringRef Bundle, 14190b57cec5SDimitry Andric ArgList &Args, DiagnosticsEngine &D, 14200b57cec5SDimitry Andric XRayInstrSet &S) { 14210b57cec5SDimitry Andric llvm::SmallVector<StringRef, 2> BundleParts; 14220b57cec5SDimitry Andric llvm::SplitString(Bundle, BundleParts, ","); 1423480093f4SDimitry Andric for (const auto &B : BundleParts) { 14240b57cec5SDimitry Andric auto Mask = parseXRayInstrValue(B); 14250b57cec5SDimitry Andric if (Mask == XRayInstrKind::None) 14260b57cec5SDimitry Andric if (B != "none") 14270b57cec5SDimitry Andric D.Report(diag::err_drv_invalid_value) << FlagName << Bundle; 14280b57cec5SDimitry Andric else 14290b57cec5SDimitry Andric S.Mask = Mask; 14300b57cec5SDimitry Andric else if (Mask == XRayInstrKind::All) 14310b57cec5SDimitry Andric S.Mask = Mask; 14320b57cec5SDimitry Andric else 14330b57cec5SDimitry Andric S.set(Mask, true); 14340b57cec5SDimitry Andric } 14350b57cec5SDimitry Andric } 14360b57cec5SDimitry Andric 1437fe6060f1SDimitry Andric static std::string serializeXRayInstrumentationBundle(const XRayInstrSet &S) { 1438fe6060f1SDimitry Andric llvm::SmallVector<StringRef, 2> BundleParts; 1439fe6060f1SDimitry Andric serializeXRayInstrValue(S, BundleParts); 1440fe6060f1SDimitry Andric std::string Buffer; 1441fe6060f1SDimitry Andric llvm::raw_string_ostream OS(Buffer); 1442fe6060f1SDimitry Andric llvm::interleave(BundleParts, OS, [&OS](StringRef Part) { OS << Part; }, ","); 14430eae32dcSDimitry Andric return Buffer; 1444fe6060f1SDimitry Andric } 1445fe6060f1SDimitry Andric 14460b57cec5SDimitry Andric // Set the profile kind using fprofile-instrument-use-path. 14470b57cec5SDimitry Andric static void setPGOUseInstrumentor(CodeGenOptions &Opts, 1448bdd1243dSDimitry Andric const Twine &ProfileName, 144906c3fb27SDimitry Andric llvm::vfs::FileSystem &FS, 1450bdd1243dSDimitry Andric DiagnosticsEngine &Diags) { 145106c3fb27SDimitry Andric auto ReaderOrErr = llvm::IndexedInstrProfReader::create(ProfileName, FS); 14520b57cec5SDimitry Andric if (auto E = ReaderOrErr.takeError()) { 1453bdd1243dSDimitry Andric unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, 1454bdd1243dSDimitry Andric "Error in reading profile %0: %1"); 1455bdd1243dSDimitry Andric llvm::handleAllErrors(std::move(E), [&](const llvm::ErrorInfoBase &EI) { 1456bdd1243dSDimitry Andric Diags.Report(DiagID) << ProfileName.str() << EI.message(); 1457bdd1243dSDimitry Andric }); 14580b57cec5SDimitry Andric return; 14590b57cec5SDimitry Andric } 14600b57cec5SDimitry Andric std::unique_ptr<llvm::IndexedInstrProfReader> PGOReader = 14610b57cec5SDimitry Andric std::move(ReaderOrErr.get()); 1462bdd1243dSDimitry Andric // Currently memprof profiles are only added at the IR level. Mark the profile 1463bdd1243dSDimitry Andric // type as IR in that case as well and the subsequent matching needs to detect 1464bdd1243dSDimitry Andric // which is available (might be one or both). 1465bdd1243dSDimitry Andric if (PGOReader->isIRLevelProfile() || PGOReader->hasMemoryProfile()) { 14660b57cec5SDimitry Andric if (PGOReader->hasCSIRLevelProfile()) 14670b57cec5SDimitry Andric Opts.setProfileUse(CodeGenOptions::ProfileCSIRInstr); 14680b57cec5SDimitry Andric else 14690b57cec5SDimitry Andric Opts.setProfileUse(CodeGenOptions::ProfileIRInstr); 14700b57cec5SDimitry Andric } else 14710b57cec5SDimitry Andric Opts.setProfileUse(CodeGenOptions::ProfileClangInstr); 14720b57cec5SDimitry Andric } 14730b57cec5SDimitry Andric 14740fca6ea1SDimitry Andric void CompilerInvocation::setDefaultPointerAuthOptions( 14750fca6ea1SDimitry Andric PointerAuthOptions &Opts, const LangOptions &LangOpts, 14760fca6ea1SDimitry Andric const llvm::Triple &Triple) { 14770fca6ea1SDimitry Andric assert(Triple.getArch() == llvm::Triple::aarch64); 14780fca6ea1SDimitry Andric if (LangOpts.PointerAuthCalls) { 14790fca6ea1SDimitry Andric using Key = PointerAuthSchema::ARM8_3Key; 14800fca6ea1SDimitry Andric using Discrimination = PointerAuthSchema::Discrimination; 14810fca6ea1SDimitry Andric // If you change anything here, be sure to update <ptrauth.h>. 14820fca6ea1SDimitry Andric Opts.FunctionPointers = PointerAuthSchema( 14830fca6ea1SDimitry Andric Key::ASIA, false, 14840fca6ea1SDimitry Andric LangOpts.PointerAuthFunctionTypeDiscrimination ? Discrimination::Type 14850fca6ea1SDimitry Andric : Discrimination::None); 14860fca6ea1SDimitry Andric 14870fca6ea1SDimitry Andric Opts.CXXVTablePointers = PointerAuthSchema( 14880fca6ea1SDimitry Andric Key::ASDA, LangOpts.PointerAuthVTPtrAddressDiscrimination, 14890fca6ea1SDimitry Andric LangOpts.PointerAuthVTPtrTypeDiscrimination ? Discrimination::Type 14900fca6ea1SDimitry Andric : Discrimination::None); 14910fca6ea1SDimitry Andric 14920fca6ea1SDimitry Andric if (LangOpts.PointerAuthTypeInfoVTPtrDiscrimination) 14930fca6ea1SDimitry Andric Opts.CXXTypeInfoVTablePointer = 14940fca6ea1SDimitry Andric PointerAuthSchema(Key::ASDA, true, Discrimination::Constant, 14950fca6ea1SDimitry Andric StdTypeInfoVTablePointerConstantDiscrimination); 14960fca6ea1SDimitry Andric else 14970fca6ea1SDimitry Andric Opts.CXXTypeInfoVTablePointer = 14980fca6ea1SDimitry Andric PointerAuthSchema(Key::ASDA, false, Discrimination::None); 14990fca6ea1SDimitry Andric 15000fca6ea1SDimitry Andric Opts.CXXVTTVTablePointers = 15010fca6ea1SDimitry Andric PointerAuthSchema(Key::ASDA, false, Discrimination::None); 15020fca6ea1SDimitry Andric Opts.CXXVirtualFunctionPointers = Opts.CXXVirtualVariadicFunctionPointers = 15030fca6ea1SDimitry Andric PointerAuthSchema(Key::ASIA, true, Discrimination::Decl); 15040fca6ea1SDimitry Andric Opts.CXXMemberFunctionPointers = 15050fca6ea1SDimitry Andric PointerAuthSchema(Key::ASIA, false, Discrimination::Type); 15060fca6ea1SDimitry Andric } 1507*62987288SDimitry Andric Opts.ReturnAddresses = LangOpts.PointerAuthReturns; 1508*62987288SDimitry Andric Opts.AuthTraps = LangOpts.PointerAuthAuthTraps; 15090fca6ea1SDimitry Andric Opts.IndirectGotos = LangOpts.PointerAuthIndirectGotos; 15100fca6ea1SDimitry Andric } 15110fca6ea1SDimitry Andric 15120fca6ea1SDimitry Andric static void parsePointerAuthOptions(PointerAuthOptions &Opts, 15130fca6ea1SDimitry Andric const LangOptions &LangOpts, 15140fca6ea1SDimitry Andric const llvm::Triple &Triple, 15150fca6ea1SDimitry Andric DiagnosticsEngine &Diags) { 1516*62987288SDimitry Andric if (!LangOpts.PointerAuthCalls && !LangOpts.PointerAuthReturns && 1517*62987288SDimitry Andric !LangOpts.PointerAuthAuthTraps && !LangOpts.PointerAuthIndirectGotos) 15180fca6ea1SDimitry Andric return; 15190fca6ea1SDimitry Andric 15200fca6ea1SDimitry Andric CompilerInvocation::setDefaultPointerAuthOptions(Opts, LangOpts, Triple); 15210fca6ea1SDimitry Andric } 15220fca6ea1SDimitry Andric 15235f757f3fSDimitry Andric void CompilerInvocationBase::GenerateCodeGenArgs(const CodeGenOptions &Opts, 15245f757f3fSDimitry Andric ArgumentConsumer Consumer, 15255f757f3fSDimitry Andric const llvm::Triple &T, 15265f757f3fSDimitry Andric const std::string &OutputFile, 1527fe6060f1SDimitry Andric const LangOptions *LangOpts) { 1528fe6060f1SDimitry Andric const CodeGenOptions &CodeGenOpts = Opts; 1529fe6060f1SDimitry Andric 1530fe6060f1SDimitry Andric if (Opts.OptimizationLevel == 0) 15315f757f3fSDimitry Andric GenerateArg(Consumer, OPT_O0); 1532fe6060f1SDimitry Andric else 15335f757f3fSDimitry Andric GenerateArg(Consumer, OPT_O, Twine(Opts.OptimizationLevel)); 1534fe6060f1SDimitry Andric 153506c3fb27SDimitry Andric #define CODEGEN_OPTION_WITH_MARSHALLING(...) \ 15365f757f3fSDimitry Andric GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__) 1537fe6060f1SDimitry Andric #include "clang/Driver/Options.inc" 1538fe6060f1SDimitry Andric #undef CODEGEN_OPTION_WITH_MARSHALLING 1539fe6060f1SDimitry Andric 1540fe6060f1SDimitry Andric if (Opts.OptimizationLevel > 0) { 1541fe6060f1SDimitry Andric if (Opts.Inlining == CodeGenOptions::NormalInlining) 15425f757f3fSDimitry Andric GenerateArg(Consumer, OPT_finline_functions); 1543fe6060f1SDimitry Andric else if (Opts.Inlining == CodeGenOptions::OnlyHintInlining) 15445f757f3fSDimitry Andric GenerateArg(Consumer, OPT_finline_hint_functions); 1545fe6060f1SDimitry Andric else if (Opts.Inlining == CodeGenOptions::OnlyAlwaysInlining) 15465f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fno_inline); 1547fe6060f1SDimitry Andric } 1548fe6060f1SDimitry Andric 1549fe6060f1SDimitry Andric if (Opts.DirectAccessExternalData && LangOpts->PICLevel != 0) 15505f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fdirect_access_external_data); 1551fe6060f1SDimitry Andric else if (!Opts.DirectAccessExternalData && LangOpts->PICLevel == 0) 15525f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fno_direct_access_external_data); 1553fe6060f1SDimitry Andric 1554bdd1243dSDimitry Andric std::optional<StringRef> DebugInfoVal; 1555fe6060f1SDimitry Andric switch (Opts.DebugInfo) { 155606c3fb27SDimitry Andric case llvm::codegenoptions::DebugLineTablesOnly: 1557fe6060f1SDimitry Andric DebugInfoVal = "line-tables-only"; 1558fe6060f1SDimitry Andric break; 155906c3fb27SDimitry Andric case llvm::codegenoptions::DebugDirectivesOnly: 1560fe6060f1SDimitry Andric DebugInfoVal = "line-directives-only"; 1561fe6060f1SDimitry Andric break; 156206c3fb27SDimitry Andric case llvm::codegenoptions::DebugInfoConstructor: 1563fe6060f1SDimitry Andric DebugInfoVal = "constructor"; 1564fe6060f1SDimitry Andric break; 156506c3fb27SDimitry Andric case llvm::codegenoptions::LimitedDebugInfo: 1566fe6060f1SDimitry Andric DebugInfoVal = "limited"; 1567fe6060f1SDimitry Andric break; 156806c3fb27SDimitry Andric case llvm::codegenoptions::FullDebugInfo: 1569fe6060f1SDimitry Andric DebugInfoVal = "standalone"; 1570fe6060f1SDimitry Andric break; 157106c3fb27SDimitry Andric case llvm::codegenoptions::UnusedTypeInfo: 1572fe6060f1SDimitry Andric DebugInfoVal = "unused-types"; 1573fe6060f1SDimitry Andric break; 157406c3fb27SDimitry Andric case llvm::codegenoptions::NoDebugInfo: // default value 1575bdd1243dSDimitry Andric DebugInfoVal = std::nullopt; 1576fe6060f1SDimitry Andric break; 157706c3fb27SDimitry Andric case llvm::codegenoptions::LocTrackingOnly: // implied value 1578bdd1243dSDimitry Andric DebugInfoVal = std::nullopt; 1579fe6060f1SDimitry Andric break; 1580fe6060f1SDimitry Andric } 1581fe6060f1SDimitry Andric if (DebugInfoVal) 15825f757f3fSDimitry Andric GenerateArg(Consumer, OPT_debug_info_kind_EQ, *DebugInfoVal); 1583fe6060f1SDimitry Andric 1584fe6060f1SDimitry Andric for (const auto &Prefix : Opts.DebugPrefixMap) 15855f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fdebug_prefix_map_EQ, 15865f757f3fSDimitry Andric Prefix.first + "=" + Prefix.second); 1587fe6060f1SDimitry Andric 1588fe6060f1SDimitry Andric for (const auto &Prefix : Opts.CoveragePrefixMap) 15895f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fcoverage_prefix_map_EQ, 15905f757f3fSDimitry Andric Prefix.first + "=" + Prefix.second); 1591fe6060f1SDimitry Andric 1592fe6060f1SDimitry Andric if (Opts.NewStructPathTBAA) 15935f757f3fSDimitry Andric GenerateArg(Consumer, OPT_new_struct_path_tbaa); 1594fe6060f1SDimitry Andric 1595fe6060f1SDimitry Andric if (Opts.OptimizeSize == 1) 15965f757f3fSDimitry Andric GenerateArg(Consumer, OPT_O, "s"); 1597fe6060f1SDimitry Andric else if (Opts.OptimizeSize == 2) 15985f757f3fSDimitry Andric GenerateArg(Consumer, OPT_O, "z"); 1599fe6060f1SDimitry Andric 1600fe6060f1SDimitry Andric // SimplifyLibCalls is set only in the absence of -fno-builtin and 1601fe6060f1SDimitry Andric // -ffreestanding. We'll consider that when generating them. 1602fe6060f1SDimitry Andric 1603fe6060f1SDimitry Andric // NoBuiltinFuncs are generated by LangOptions. 1604fe6060f1SDimitry Andric 1605fe6060f1SDimitry Andric if (Opts.UnrollLoops && Opts.OptimizationLevel <= 1) 16065f757f3fSDimitry Andric GenerateArg(Consumer, OPT_funroll_loops); 1607fe6060f1SDimitry Andric else if (!Opts.UnrollLoops && Opts.OptimizationLevel > 1) 16085f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fno_unroll_loops); 1609fe6060f1SDimitry Andric 1610fe6060f1SDimitry Andric if (!Opts.BinutilsVersion.empty()) 16115f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fbinutils_version_EQ, Opts.BinutilsVersion); 1612fe6060f1SDimitry Andric 1613fe6060f1SDimitry Andric if (Opts.DebugNameTable == 1614fe6060f1SDimitry Andric static_cast<unsigned>(llvm::DICompileUnit::DebugNameTableKind::GNU)) 16155f757f3fSDimitry Andric GenerateArg(Consumer, OPT_ggnu_pubnames); 1616fe6060f1SDimitry Andric else if (Opts.DebugNameTable == 1617fe6060f1SDimitry Andric static_cast<unsigned>( 1618fe6060f1SDimitry Andric llvm::DICompileUnit::DebugNameTableKind::Default)) 16195f757f3fSDimitry Andric GenerateArg(Consumer, OPT_gpubnames); 1620fe6060f1SDimitry Andric 16210fca6ea1SDimitry Andric if (Opts.DebugTemplateAlias) 16220fca6ea1SDimitry Andric GenerateArg(Consumer, OPT_gtemplate_alias); 16230fca6ea1SDimitry Andric 1624349cc55cSDimitry Andric auto TNK = Opts.getDebugSimpleTemplateNames(); 162506c3fb27SDimitry Andric if (TNK != llvm::codegenoptions::DebugTemplateNamesKind::Full) { 162606c3fb27SDimitry Andric if (TNK == llvm::codegenoptions::DebugTemplateNamesKind::Simple) 16275f757f3fSDimitry Andric GenerateArg(Consumer, OPT_gsimple_template_names_EQ, "simple"); 162806c3fb27SDimitry Andric else if (TNK == llvm::codegenoptions::DebugTemplateNamesKind::Mangled) 16295f757f3fSDimitry Andric GenerateArg(Consumer, OPT_gsimple_template_names_EQ, "mangled"); 1630349cc55cSDimitry Andric } 1631fe6060f1SDimitry Andric // ProfileInstrumentUsePath is marshalled automatically, no need to generate 1632fe6060f1SDimitry Andric // it or PGOUseInstrumentor. 1633fe6060f1SDimitry Andric 1634fe6060f1SDimitry Andric if (Opts.TimePasses) { 1635fe6060f1SDimitry Andric if (Opts.TimePassesPerRun) 16365f757f3fSDimitry Andric GenerateArg(Consumer, OPT_ftime_report_EQ, "per-pass-run"); 1637fe6060f1SDimitry Andric else 16385f757f3fSDimitry Andric GenerateArg(Consumer, OPT_ftime_report); 1639fe6060f1SDimitry Andric } 1640fe6060f1SDimitry Andric 1641fe6060f1SDimitry Andric if (Opts.PrepareForLTO && !Opts.PrepareForThinLTO) 16425f757f3fSDimitry Andric GenerateArg(Consumer, OPT_flto_EQ, "full"); 1643fe6060f1SDimitry Andric 1644fe6060f1SDimitry Andric if (Opts.PrepareForThinLTO) 16455f757f3fSDimitry Andric GenerateArg(Consumer, OPT_flto_EQ, "thin"); 1646fe6060f1SDimitry Andric 1647fe6060f1SDimitry Andric if (!Opts.ThinLTOIndexFile.empty()) 16485f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fthinlto_index_EQ, Opts.ThinLTOIndexFile); 1649fe6060f1SDimitry Andric 1650fe6060f1SDimitry Andric if (Opts.SaveTempsFilePrefix == OutputFile) 16515f757f3fSDimitry Andric GenerateArg(Consumer, OPT_save_temps_EQ, "obj"); 1652fe6060f1SDimitry Andric 1653fe6060f1SDimitry Andric StringRef MemProfileBasename("memprof.profraw"); 1654fe6060f1SDimitry Andric if (!Opts.MemoryProfileOutput.empty()) { 1655fe6060f1SDimitry Andric if (Opts.MemoryProfileOutput == MemProfileBasename) { 16565f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fmemory_profile); 1657fe6060f1SDimitry Andric } else { 1658fe6060f1SDimitry Andric size_t ArgLength = 1659fe6060f1SDimitry Andric Opts.MemoryProfileOutput.size() - MemProfileBasename.size(); 16605f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fmemory_profile_EQ, 16615f757f3fSDimitry Andric Opts.MemoryProfileOutput.substr(0, ArgLength)); 1662fe6060f1SDimitry Andric } 1663fe6060f1SDimitry Andric } 1664fe6060f1SDimitry Andric 1665fe6060f1SDimitry Andric if (memcmp(Opts.CoverageVersion, "408*", 4) != 0) 16665f757f3fSDimitry Andric GenerateArg(Consumer, OPT_coverage_version_EQ, 16675f757f3fSDimitry Andric StringRef(Opts.CoverageVersion, 4)); 1668fe6060f1SDimitry Andric 1669fe6060f1SDimitry Andric // TODO: Check if we need to generate arguments stored in CmdArgs. (Namely 1670fe6060f1SDimitry Andric // '-fembed_bitcode', which does not map to any CompilerInvocation field and 1671fe6060f1SDimitry Andric // won't be generated.) 1672fe6060f1SDimitry Andric 1673fe6060f1SDimitry Andric if (Opts.XRayInstrumentationBundle.Mask != XRayInstrKind::All) { 1674fe6060f1SDimitry Andric std::string InstrBundle = 1675fe6060f1SDimitry Andric serializeXRayInstrumentationBundle(Opts.XRayInstrumentationBundle); 1676fe6060f1SDimitry Andric if (!InstrBundle.empty()) 16775f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fxray_instrumentation_bundle, InstrBundle); 1678fe6060f1SDimitry Andric } 1679fe6060f1SDimitry Andric 1680fe6060f1SDimitry Andric if (Opts.CFProtectionReturn && Opts.CFProtectionBranch) 16815f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fcf_protection_EQ, "full"); 1682fe6060f1SDimitry Andric else if (Opts.CFProtectionReturn) 16835f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fcf_protection_EQ, "return"); 1684fe6060f1SDimitry Andric else if (Opts.CFProtectionBranch) 16855f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fcf_protection_EQ, "branch"); 1686fe6060f1SDimitry Andric 1687753f127fSDimitry Andric if (Opts.FunctionReturnThunks) 16885f757f3fSDimitry Andric GenerateArg(Consumer, OPT_mfunction_return_EQ, "thunk-extern"); 1689753f127fSDimitry Andric 1690fe6060f1SDimitry Andric for (const auto &F : Opts.LinkBitcodeFiles) { 1691fe6060f1SDimitry Andric bool Builtint = F.LinkFlags == llvm::Linker::Flags::LinkOnlyNeeded && 1692fe6060f1SDimitry Andric F.PropagateAttrs && F.Internalize; 16935f757f3fSDimitry Andric GenerateArg(Consumer, 1694fe6060f1SDimitry Andric Builtint ? OPT_mlink_builtin_bitcode : OPT_mlink_bitcode_file, 16955f757f3fSDimitry Andric F.Filename); 1696fe6060f1SDimitry Andric } 1697fe6060f1SDimitry Andric 169806c3fb27SDimitry Andric if (Opts.EmulatedTLS) 16995f757f3fSDimitry Andric GenerateArg(Consumer, OPT_femulated_tls); 1700fe6060f1SDimitry Andric 1701fe6060f1SDimitry Andric if (Opts.FPDenormalMode != llvm::DenormalMode::getIEEE()) 17025f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fdenormal_fp_math_EQ, Opts.FPDenormalMode.str()); 1703fe6060f1SDimitry Andric 170481ad6265SDimitry Andric if ((Opts.FPDenormalMode != Opts.FP32DenormalMode) || 170581ad6265SDimitry Andric (Opts.FP32DenormalMode != llvm::DenormalMode::getIEEE())) 17065f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fdenormal_fp_math_f32_EQ, 17075f757f3fSDimitry Andric Opts.FP32DenormalMode.str()); 1708fe6060f1SDimitry Andric 1709fe6060f1SDimitry Andric if (Opts.StructReturnConvention == CodeGenOptions::SRCK_OnStack) { 1710fe6060f1SDimitry Andric OptSpecifier Opt = 1711fe6060f1SDimitry Andric T.isPPC32() ? OPT_maix_struct_return : OPT_fpcc_struct_return; 17125f757f3fSDimitry Andric GenerateArg(Consumer, Opt); 1713fe6060f1SDimitry Andric } else if (Opts.StructReturnConvention == CodeGenOptions::SRCK_InRegs) { 1714fe6060f1SDimitry Andric OptSpecifier Opt = 1715fe6060f1SDimitry Andric T.isPPC32() ? OPT_msvr4_struct_return : OPT_freg_struct_return; 17165f757f3fSDimitry Andric GenerateArg(Consumer, Opt); 1717fe6060f1SDimitry Andric } 1718fe6060f1SDimitry Andric 1719fe6060f1SDimitry Andric if (Opts.EnableAIXExtendedAltivecABI) 17205f757f3fSDimitry Andric GenerateArg(Consumer, OPT_mabi_EQ_vec_extabi); 1721fe6060f1SDimitry Andric 172206c3fb27SDimitry Andric if (Opts.XCOFFReadOnlyPointers) 17235f757f3fSDimitry Andric GenerateArg(Consumer, OPT_mxcoff_roptr); 172406c3fb27SDimitry Andric 1725fe6060f1SDimitry Andric if (!Opts.OptRecordPasses.empty()) 17265f757f3fSDimitry Andric GenerateArg(Consumer, OPT_opt_record_passes, Opts.OptRecordPasses); 1727fe6060f1SDimitry Andric 1728fe6060f1SDimitry Andric if (!Opts.OptRecordFormat.empty()) 17295f757f3fSDimitry Andric GenerateArg(Consumer, OPT_opt_record_format, Opts.OptRecordFormat); 1730fe6060f1SDimitry Andric 17315f757f3fSDimitry Andric GenerateOptimizationRemark(Consumer, OPT_Rpass_EQ, "pass", 1732fe6060f1SDimitry Andric Opts.OptimizationRemark); 1733fe6060f1SDimitry Andric 17345f757f3fSDimitry Andric GenerateOptimizationRemark(Consumer, OPT_Rpass_missed_EQ, "pass-missed", 1735fe6060f1SDimitry Andric Opts.OptimizationRemarkMissed); 1736fe6060f1SDimitry Andric 17375f757f3fSDimitry Andric GenerateOptimizationRemark(Consumer, OPT_Rpass_analysis_EQ, "pass-analysis", 1738fe6060f1SDimitry Andric Opts.OptimizationRemarkAnalysis); 1739fe6060f1SDimitry Andric 17405f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fdiagnostics_hotness_threshold_EQ, 1741fe6060f1SDimitry Andric Opts.DiagnosticsHotnessThreshold 1742fe6060f1SDimitry Andric ? Twine(*Opts.DiagnosticsHotnessThreshold) 17435f757f3fSDimitry Andric : "auto"); 1744fe6060f1SDimitry Andric 17455f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fdiagnostics_misexpect_tolerance_EQ, 17465f757f3fSDimitry Andric Twine(*Opts.DiagnosticsMisExpectTolerance)); 174781ad6265SDimitry Andric 1748fe6060f1SDimitry Andric for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeRecover)) 17495f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fsanitize_recover_EQ, Sanitizer); 1750fe6060f1SDimitry Andric 1751fe6060f1SDimitry Andric for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeTrap)) 17525f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fsanitize_trap_EQ, Sanitizer); 1753fe6060f1SDimitry Andric 1754fe6060f1SDimitry Andric if (!Opts.EmitVersionIdentMetadata) 17555f757f3fSDimitry Andric GenerateArg(Consumer, OPT_Qn); 1756fe6060f1SDimitry Andric 1757fe6060f1SDimitry Andric switch (Opts.FiniteLoops) { 1758fe6060f1SDimitry Andric case CodeGenOptions::FiniteLoopsKind::Language: 1759fe6060f1SDimitry Andric break; 1760fe6060f1SDimitry Andric case CodeGenOptions::FiniteLoopsKind::Always: 17615f757f3fSDimitry Andric GenerateArg(Consumer, OPT_ffinite_loops); 1762fe6060f1SDimitry Andric break; 1763fe6060f1SDimitry Andric case CodeGenOptions::FiniteLoopsKind::Never: 17645f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fno_finite_loops); 1765fe6060f1SDimitry Andric break; 1766fe6060f1SDimitry Andric } 1767fe6060f1SDimitry Andric } 1768fe6060f1SDimitry Andric 1769e8d8bef9SDimitry Andric bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, 1770e8d8bef9SDimitry Andric InputKind IK, 17710b57cec5SDimitry Andric DiagnosticsEngine &Diags, 1772e8d8bef9SDimitry Andric const llvm::Triple &T, 1773e8d8bef9SDimitry Andric const std::string &OutputFile, 1774e8d8bef9SDimitry Andric const LangOptions &LangOptsRef) { 1775fe6060f1SDimitry Andric unsigned NumErrorsBefore = Diags.getNumErrors(); 17760b57cec5SDimitry Andric 17770b57cec5SDimitry Andric unsigned OptimizationLevel = getOptimizationLevel(Args, IK, Diags); 17780b57cec5SDimitry Andric // TODO: This could be done in Driver 17790b57cec5SDimitry Andric unsigned MaxOptLevel = 3; 17800b57cec5SDimitry Andric if (OptimizationLevel > MaxOptLevel) { 17810b57cec5SDimitry Andric // If the optimization level is not supported, fall back on the default 17820b57cec5SDimitry Andric // optimization 17830b57cec5SDimitry Andric Diags.Report(diag::warn_drv_optimization_value) 17840b57cec5SDimitry Andric << Args.getLastArg(OPT_O)->getAsString(Args) << "-O" << MaxOptLevel; 17850b57cec5SDimitry Andric OptimizationLevel = MaxOptLevel; 17860b57cec5SDimitry Andric } 17870b57cec5SDimitry Andric Opts.OptimizationLevel = OptimizationLevel; 17880b57cec5SDimitry Andric 1789e8d8bef9SDimitry Andric // The key paths of codegen options defined in Options.td start with 1790e8d8bef9SDimitry Andric // "CodeGenOpts.". Let's provide the expected variable name and type. 1791e8d8bef9SDimitry Andric CodeGenOptions &CodeGenOpts = Opts; 1792e8d8bef9SDimitry Andric // Some codegen options depend on language options. Let's provide the expected 1793e8d8bef9SDimitry Andric // variable name and type. 1794e8d8bef9SDimitry Andric const LangOptions *LangOpts = &LangOptsRef; 1795e8d8bef9SDimitry Andric 179606c3fb27SDimitry Andric #define CODEGEN_OPTION_WITH_MARSHALLING(...) \ 179706c3fb27SDimitry Andric PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__) 1798e8d8bef9SDimitry Andric #include "clang/Driver/Options.inc" 1799e8d8bef9SDimitry Andric #undef CODEGEN_OPTION_WITH_MARSHALLING 1800e8d8bef9SDimitry Andric 18010b57cec5SDimitry Andric // At O0 we want to fully disable inlining outside of cases marked with 18020b57cec5SDimitry Andric // 'alwaysinline' that are required for correctness. 180381ad6265SDimitry Andric if (Opts.OptimizationLevel == 0) { 180481ad6265SDimitry Andric Opts.setInlining(CodeGenOptions::OnlyAlwaysInlining); 180581ad6265SDimitry Andric } else if (const Arg *A = Args.getLastArg(options::OPT_finline_functions, 180681ad6265SDimitry Andric options::OPT_finline_hint_functions, 180781ad6265SDimitry Andric options::OPT_fno_inline_functions, 180881ad6265SDimitry Andric options::OPT_fno_inline)) { 18090b57cec5SDimitry Andric // Explicit inlining flags can disable some or all inlining even at 18100b57cec5SDimitry Andric // optimization levels above zero. 181181ad6265SDimitry Andric if (A->getOption().matches(options::OPT_finline_functions)) 18120b57cec5SDimitry Andric Opts.setInlining(CodeGenOptions::NormalInlining); 181381ad6265SDimitry Andric else if (A->getOption().matches(options::OPT_finline_hint_functions)) 18140b57cec5SDimitry Andric Opts.setInlining(CodeGenOptions::OnlyHintInlining); 18150b57cec5SDimitry Andric else 18160b57cec5SDimitry Andric Opts.setInlining(CodeGenOptions::OnlyAlwaysInlining); 181781ad6265SDimitry Andric } else { 181881ad6265SDimitry Andric Opts.setInlining(CodeGenOptions::NormalInlining); 18190b57cec5SDimitry Andric } 18200b57cec5SDimitry Andric 1821e8d8bef9SDimitry Andric // PIC defaults to -fno-direct-access-external-data while non-PIC defaults to 1822e8d8bef9SDimitry Andric // -fdirect-access-external-data. 1823e8d8bef9SDimitry Andric Opts.DirectAccessExternalData = 1824e8d8bef9SDimitry Andric Args.hasArg(OPT_fdirect_access_external_data) || 1825e8d8bef9SDimitry Andric (!Args.hasArg(OPT_fno_direct_access_external_data) && 1826fe6060f1SDimitry Andric LangOpts->PICLevel == 0); 1827fe6060f1SDimitry Andric 1828fe6060f1SDimitry Andric if (Arg *A = Args.getLastArg(OPT_debug_info_kind_EQ)) { 1829fe6060f1SDimitry Andric unsigned Val = 1830fe6060f1SDimitry Andric llvm::StringSwitch<unsigned>(A->getValue()) 183106c3fb27SDimitry Andric .Case("line-tables-only", llvm::codegenoptions::DebugLineTablesOnly) 183206c3fb27SDimitry Andric .Case("line-directives-only", 183306c3fb27SDimitry Andric llvm::codegenoptions::DebugDirectivesOnly) 183406c3fb27SDimitry Andric .Case("constructor", llvm::codegenoptions::DebugInfoConstructor) 183506c3fb27SDimitry Andric .Case("limited", llvm::codegenoptions::LimitedDebugInfo) 183606c3fb27SDimitry Andric .Case("standalone", llvm::codegenoptions::FullDebugInfo) 183706c3fb27SDimitry Andric .Case("unused-types", llvm::codegenoptions::UnusedTypeInfo) 1838fe6060f1SDimitry Andric .Default(~0U); 1839fe6060f1SDimitry Andric if (Val == ~0U) 1840fe6060f1SDimitry Andric Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) 1841fe6060f1SDimitry Andric << A->getValue(); 1842fe6060f1SDimitry Andric else 184306c3fb27SDimitry Andric Opts.setDebugInfo(static_cast<llvm::codegenoptions::DebugInfoKind>(Val)); 1844fe6060f1SDimitry Andric } 18450b57cec5SDimitry Andric 1846e8d8bef9SDimitry Andric // If -fuse-ctor-homing is set and limited debug info is already on, then use 1847fe6060f1SDimitry Andric // constructor homing, and vice versa for -fno-use-ctor-homing. 1848fe6060f1SDimitry Andric if (const Arg *A = 1849fe6060f1SDimitry Andric Args.getLastArg(OPT_fuse_ctor_homing, OPT_fno_use_ctor_homing)) { 1850fe6060f1SDimitry Andric if (A->getOption().matches(OPT_fuse_ctor_homing) && 185106c3fb27SDimitry Andric Opts.getDebugInfo() == llvm::codegenoptions::LimitedDebugInfo) 185206c3fb27SDimitry Andric Opts.setDebugInfo(llvm::codegenoptions::DebugInfoConstructor); 1853fe6060f1SDimitry Andric if (A->getOption().matches(OPT_fno_use_ctor_homing) && 185406c3fb27SDimitry Andric Opts.getDebugInfo() == llvm::codegenoptions::DebugInfoConstructor) 185506c3fb27SDimitry Andric Opts.setDebugInfo(llvm::codegenoptions::LimitedDebugInfo); 1856fe6060f1SDimitry Andric } 18570b57cec5SDimitry Andric 18585ffd83dbSDimitry Andric for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) { 18595ffd83dbSDimitry Andric auto Split = StringRef(Arg).split('='); 186006c3fb27SDimitry Andric Opts.DebugPrefixMap.emplace_back(Split.first, Split.second); 18615ffd83dbSDimitry Andric } 18620b57cec5SDimitry Andric 1863fe6060f1SDimitry Andric for (const auto &Arg : Args.getAllArgValues(OPT_fcoverage_prefix_map_EQ)) { 1864e8d8bef9SDimitry Andric auto Split = StringRef(Arg).split('='); 186506c3fb27SDimitry Andric Opts.CoveragePrefixMap.emplace_back(Split.first, Split.second); 1866e8d8bef9SDimitry Andric } 18670b57cec5SDimitry Andric 1868a7dea167SDimitry Andric const llvm::Triple::ArchType DebugEntryValueArchs[] = { 1869a7dea167SDimitry Andric llvm::Triple::x86, llvm::Triple::x86_64, llvm::Triple::aarch64, 18705ffd83dbSDimitry Andric llvm::Triple::arm, llvm::Triple::armeb, llvm::Triple::mips, 18715ffd83dbSDimitry Andric llvm::Triple::mipsel, llvm::Triple::mips64, llvm::Triple::mips64el}; 1872a7dea167SDimitry Andric 1873480093f4SDimitry Andric if (Opts.OptimizationLevel > 0 && Opts.hasReducedDebugInfo() && 1874a7dea167SDimitry Andric llvm::is_contained(DebugEntryValueArchs, T.getArch())) 18755ffd83dbSDimitry Andric Opts.EmitCallSiteInfo = true; 18760b57cec5SDimitry Andric 1877fe6060f1SDimitry Andric if (!Opts.EnableDIPreservationVerify && Opts.DIBugsReportFilePath.size()) { 1878fe6060f1SDimitry Andric Diags.Report(diag::warn_ignoring_verify_debuginfo_preserve_export) 1879fe6060f1SDimitry Andric << Opts.DIBugsReportFilePath; 1880fe6060f1SDimitry Andric Opts.DIBugsReportFilePath = ""; 1881fe6060f1SDimitry Andric } 1882fe6060f1SDimitry Andric 18830b57cec5SDimitry Andric Opts.NewStructPathTBAA = !Args.hasArg(OPT_no_struct_path_tbaa) && 18840b57cec5SDimitry Andric Args.hasArg(OPT_new_struct_path_tbaa); 18850b57cec5SDimitry Andric Opts.OptimizeSize = getOptimizationLevelSize(Args); 1886fe6060f1SDimitry Andric Opts.SimplifyLibCalls = !LangOpts->NoBuiltin; 18870b57cec5SDimitry Andric if (Opts.SimplifyLibCalls) 1888fe6060f1SDimitry Andric Opts.NoBuiltinFuncs = LangOpts->NoBuiltinFuncs; 18890b57cec5SDimitry Andric Opts.UnrollLoops = 18900b57cec5SDimitry Andric Args.hasFlag(OPT_funroll_loops, OPT_fno_unroll_loops, 18910b57cec5SDimitry Andric (Opts.OptimizationLevel > 1)); 1892e8d8bef9SDimitry Andric Opts.BinutilsVersion = 1893e8d8bef9SDimitry Andric std::string(Args.getLastArgValue(OPT_fbinutils_version_EQ)); 1894e8d8bef9SDimitry Andric 18950fca6ea1SDimitry Andric Opts.DebugTemplateAlias = Args.hasArg(OPT_gtemplate_alias); 18960fca6ea1SDimitry Andric 18970b57cec5SDimitry Andric Opts.DebugNameTable = static_cast<unsigned>( 18980b57cec5SDimitry Andric Args.hasArg(OPT_ggnu_pubnames) 18990b57cec5SDimitry Andric ? llvm::DICompileUnit::DebugNameTableKind::GNU 19000b57cec5SDimitry Andric : Args.hasArg(OPT_gpubnames) 19010b57cec5SDimitry Andric ? llvm::DICompileUnit::DebugNameTableKind::Default 19020b57cec5SDimitry Andric : llvm::DICompileUnit::DebugNameTableKind::None); 1903349cc55cSDimitry Andric if (const Arg *A = Args.getLastArg(OPT_gsimple_template_names_EQ)) { 1904349cc55cSDimitry Andric StringRef Value = A->getValue(); 1905349cc55cSDimitry Andric if (Value != "simple" && Value != "mangled") 1906349cc55cSDimitry Andric Diags.Report(diag::err_drv_unsupported_option_argument) 1907bdd1243dSDimitry Andric << A->getSpelling() << A->getValue(); 1908349cc55cSDimitry Andric Opts.setDebugSimpleTemplateNames( 1909349cc55cSDimitry Andric StringRef(A->getValue()) == "simple" 191006c3fb27SDimitry Andric ? llvm::codegenoptions::DebugTemplateNamesKind::Simple 191106c3fb27SDimitry Andric : llvm::codegenoptions::DebugTemplateNamesKind::Mangled); 1912349cc55cSDimitry Andric } 19130b57cec5SDimitry Andric 1914e8d8bef9SDimitry Andric if (const Arg *A = Args.getLastArg(OPT_ftime_report, OPT_ftime_report_EQ)) { 1915e8d8bef9SDimitry Andric Opts.TimePasses = true; 1916e8d8bef9SDimitry Andric 1917e8d8bef9SDimitry Andric // -ftime-report= is only for new pass manager. 1918e8d8bef9SDimitry Andric if (A->getOption().getID() == OPT_ftime_report_EQ) { 1919e8d8bef9SDimitry Andric StringRef Val = A->getValue(); 1920e8d8bef9SDimitry Andric if (Val == "per-pass") 1921e8d8bef9SDimitry Andric Opts.TimePassesPerRun = false; 1922e8d8bef9SDimitry Andric else if (Val == "per-pass-run") 1923e8d8bef9SDimitry Andric Opts.TimePassesPerRun = true; 1924e8d8bef9SDimitry Andric else 19250b57cec5SDimitry Andric Diags.Report(diag::err_drv_invalid_value) 1926e8d8bef9SDimitry Andric << A->getAsString(Args) << A->getValue(); 1927e8d8bef9SDimitry Andric } 1928e8d8bef9SDimitry Andric } 19295ffd83dbSDimitry Andric 1930349cc55cSDimitry Andric Opts.PrepareForLTO = false; 19310b57cec5SDimitry Andric Opts.PrepareForThinLTO = false; 19320b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(OPT_flto_EQ)) { 1933349cc55cSDimitry Andric Opts.PrepareForLTO = true; 19340b57cec5SDimitry Andric StringRef S = A->getValue(); 19350b57cec5SDimitry Andric if (S == "thin") 19360b57cec5SDimitry Andric Opts.PrepareForThinLTO = true; 19370b57cec5SDimitry Andric else if (S != "full") 19380b57cec5SDimitry Andric Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << S; 193906c3fb27SDimitry Andric if (Args.hasArg(OPT_funified_lto)) 194006c3fb27SDimitry Andric Opts.PrepareForThinLTO = true; 19410b57cec5SDimitry Andric } 19420b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(OPT_fthinlto_index_EQ)) { 1943a7dea167SDimitry Andric if (IK.getLanguage() != Language::LLVM_IR) 19440b57cec5SDimitry Andric Diags.Report(diag::err_drv_argument_only_allowed_with) 19450b57cec5SDimitry Andric << A->getAsString(Args) << "-x ir"; 19465ffd83dbSDimitry Andric Opts.ThinLTOIndexFile = 19475ffd83dbSDimitry Andric std::string(Args.getLastArgValue(OPT_fthinlto_index_EQ)); 19480b57cec5SDimitry Andric } 19490b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(OPT_save_temps_EQ)) 19500b57cec5SDimitry Andric Opts.SaveTempsFilePrefix = 19510b57cec5SDimitry Andric llvm::StringSwitch<std::string>(A->getValue()) 1952e8d8bef9SDimitry Andric .Case("obj", OutputFile) 1953e8d8bef9SDimitry Andric .Default(llvm::sys::path::filename(OutputFile).str()); 19540b57cec5SDimitry Andric 1955e8d8bef9SDimitry Andric // The memory profile runtime appends the pid to make this name more unique. 1956e8d8bef9SDimitry Andric const char *MemProfileBasename = "memprof.profraw"; 1957e8d8bef9SDimitry Andric if (Args.hasArg(OPT_fmemory_profile_EQ)) { 1958e8d8bef9SDimitry Andric SmallString<128> Path( 1959e8d8bef9SDimitry Andric std::string(Args.getLastArgValue(OPT_fmemory_profile_EQ))); 1960e8d8bef9SDimitry Andric llvm::sys::path::append(Path, MemProfileBasename); 1961e8d8bef9SDimitry Andric Opts.MemoryProfileOutput = std::string(Path); 1962e8d8bef9SDimitry Andric } else if (Args.hasArg(OPT_fmemory_profile)) 1963e8d8bef9SDimitry Andric Opts.MemoryProfileOutput = MemProfileBasename; 19640b57cec5SDimitry Andric 1965fe6060f1SDimitry Andric memcpy(Opts.CoverageVersion, "408*", 4); 196606c3fb27SDimitry Andric if (Opts.CoverageNotesFile.size() || Opts.CoverageDataFile.size()) { 19670b57cec5SDimitry Andric if (Args.hasArg(OPT_coverage_version_EQ)) { 19680b57cec5SDimitry Andric StringRef CoverageVersion = Args.getLastArgValue(OPT_coverage_version_EQ); 19690b57cec5SDimitry Andric if (CoverageVersion.size() != 4) { 19700b57cec5SDimitry Andric Diags.Report(diag::err_drv_invalid_value) 19710b57cec5SDimitry Andric << Args.getLastArg(OPT_coverage_version_EQ)->getAsString(Args) 19720b57cec5SDimitry Andric << CoverageVersion; 19730b57cec5SDimitry Andric } else { 19740b57cec5SDimitry Andric memcpy(Opts.CoverageVersion, CoverageVersion.data(), 4); 19750b57cec5SDimitry Andric } 19760b57cec5SDimitry Andric } 19770b57cec5SDimitry Andric } 19780b57cec5SDimitry Andric // FIXME: For backend options that are not yet recorded as function 19790b57cec5SDimitry Andric // attributes in the IR, keep track of them so we can embed them in a 19800b57cec5SDimitry Andric // separate data section and use them when building the bitcode. 19810b57cec5SDimitry Andric for (const auto &A : Args) { 19820b57cec5SDimitry Andric // Do not encode output and input. 19830b57cec5SDimitry Andric if (A->getOption().getID() == options::OPT_o || 19840b57cec5SDimitry Andric A->getOption().getID() == options::OPT_INPUT || 19850b57cec5SDimitry Andric A->getOption().getID() == options::OPT_x || 19860b57cec5SDimitry Andric A->getOption().getID() == options::OPT_fembed_bitcode || 19875ffd83dbSDimitry Andric A->getOption().matches(options::OPT_W_Group)) 19880b57cec5SDimitry Andric continue; 19890b57cec5SDimitry Andric ArgStringList ASL; 19900b57cec5SDimitry Andric A->render(Args, ASL); 19910b57cec5SDimitry Andric for (const auto &arg : ASL) { 19920b57cec5SDimitry Andric StringRef ArgStr(arg); 19930b57cec5SDimitry Andric Opts.CmdArgs.insert(Opts.CmdArgs.end(), ArgStr.begin(), ArgStr.end()); 19940b57cec5SDimitry Andric // using \00 to separate each commandline options. 19950b57cec5SDimitry Andric Opts.CmdArgs.push_back('\0'); 19960b57cec5SDimitry Andric } 19970b57cec5SDimitry Andric } 19980b57cec5SDimitry Andric 19990b57cec5SDimitry Andric auto XRayInstrBundles = 20000b57cec5SDimitry Andric Args.getAllArgValues(OPT_fxray_instrumentation_bundle); 20010b57cec5SDimitry Andric if (XRayInstrBundles.empty()) 20020b57cec5SDimitry Andric Opts.XRayInstrumentationBundle.Mask = XRayInstrKind::All; 20030b57cec5SDimitry Andric else 20040b57cec5SDimitry Andric for (const auto &A : XRayInstrBundles) 20050b57cec5SDimitry Andric parseXRayInstrumentationBundle("-fxray-instrumentation-bundle=", A, Args, 20060b57cec5SDimitry Andric Diags, Opts.XRayInstrumentationBundle); 20070b57cec5SDimitry Andric 20080b57cec5SDimitry Andric if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) { 20090b57cec5SDimitry Andric StringRef Name = A->getValue(); 20100b57cec5SDimitry Andric if (Name == "full") { 20110b57cec5SDimitry Andric Opts.CFProtectionReturn = 1; 20120b57cec5SDimitry Andric Opts.CFProtectionBranch = 1; 20130b57cec5SDimitry Andric } else if (Name == "return") 20140b57cec5SDimitry Andric Opts.CFProtectionReturn = 1; 20150b57cec5SDimitry Andric else if (Name == "branch") 20160b57cec5SDimitry Andric Opts.CFProtectionBranch = 1; 2017fe6060f1SDimitry Andric else if (Name != "none") 20180b57cec5SDimitry Andric Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name; 20190b57cec5SDimitry Andric } 20200b57cec5SDimitry Andric 2021753f127fSDimitry Andric if (const Arg *A = Args.getLastArg(OPT_mfunction_return_EQ)) { 2022753f127fSDimitry Andric auto Val = llvm::StringSwitch<llvm::FunctionReturnThunksKind>(A->getValue()) 2023753f127fSDimitry Andric .Case("keep", llvm::FunctionReturnThunksKind::Keep) 2024753f127fSDimitry Andric .Case("thunk-extern", llvm::FunctionReturnThunksKind::Extern) 2025753f127fSDimitry Andric .Default(llvm::FunctionReturnThunksKind::Invalid); 2026753f127fSDimitry Andric // SystemZ might want to add support for "expolines." 2027753f127fSDimitry Andric if (!T.isX86()) 2028753f127fSDimitry Andric Diags.Report(diag::err_drv_argument_not_allowed_with) 2029753f127fSDimitry Andric << A->getSpelling() << T.getTriple(); 2030753f127fSDimitry Andric else if (Val == llvm::FunctionReturnThunksKind::Invalid) 2031753f127fSDimitry Andric Diags.Report(diag::err_drv_invalid_value) 2032753f127fSDimitry Andric << A->getAsString(Args) << A->getValue(); 2033753f127fSDimitry Andric else if (Val == llvm::FunctionReturnThunksKind::Extern && 20340fca6ea1SDimitry Andric Args.getLastArgValue(OPT_mcmodel_EQ) == "large") 2035753f127fSDimitry Andric Diags.Report(diag::err_drv_argument_not_allowed_with) 2036753f127fSDimitry Andric << A->getAsString(Args) 2037753f127fSDimitry Andric << Args.getLastArg(OPT_mcmodel_EQ)->getAsString(Args); 2038753f127fSDimitry Andric else 2039753f127fSDimitry Andric Opts.FunctionReturnThunks = static_cast<unsigned>(Val); 2040753f127fSDimitry Andric } 2041753f127fSDimitry Andric 20420b57cec5SDimitry Andric for (auto *A : 20430b57cec5SDimitry Andric Args.filtered(OPT_mlink_bitcode_file, OPT_mlink_builtin_bitcode)) { 20440b57cec5SDimitry Andric CodeGenOptions::BitcodeFileToLink F; 20450b57cec5SDimitry Andric F.Filename = A->getValue(); 20460b57cec5SDimitry Andric if (A->getOption().matches(OPT_mlink_builtin_bitcode)) { 20470b57cec5SDimitry Andric F.LinkFlags = llvm::Linker::Flags::LinkOnlyNeeded; 20480b57cec5SDimitry Andric // When linking CUDA bitcode, propagate function attributes so that 20490b57cec5SDimitry Andric // e.g. libdevice gets fast-math attrs if we're building with fast-math. 20500b57cec5SDimitry Andric F.PropagateAttrs = true; 20510b57cec5SDimitry Andric F.Internalize = true; 20520b57cec5SDimitry Andric } 20530b57cec5SDimitry Andric Opts.LinkBitcodeFiles.push_back(F); 20540b57cec5SDimitry Andric } 20550b57cec5SDimitry Andric 20560b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_EQ)) { 20570b57cec5SDimitry Andric StringRef Val = A->getValue(); 2058480093f4SDimitry Andric Opts.FPDenormalMode = llvm::parseDenormalFPAttribute(Val); 205981ad6265SDimitry Andric Opts.FP32DenormalMode = Opts.FPDenormalMode; 20605ffd83dbSDimitry Andric if (!Opts.FPDenormalMode.isValid()) 20615ffd83dbSDimitry Andric Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val; 20625ffd83dbSDimitry Andric } 20635ffd83dbSDimitry Andric 20645ffd83dbSDimitry Andric if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_f32_EQ)) { 20655ffd83dbSDimitry Andric StringRef Val = A->getValue(); 20665ffd83dbSDimitry Andric Opts.FP32DenormalMode = llvm::parseDenormalFPAttribute(Val); 20675ffd83dbSDimitry Andric if (!Opts.FP32DenormalMode.isValid()) 20680b57cec5SDimitry Andric Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val; 20690b57cec5SDimitry Andric } 20700b57cec5SDimitry Andric 2071e86cf8adSDimitry Andric // X86_32 has -fppc-struct-return and -freg-struct-return. 2072e86cf8adSDimitry Andric // PPC32 has -maix-struct-return and -msvr4-struct-return. 2073e86cf8adSDimitry Andric if (Arg *A = 2074e86cf8adSDimitry Andric Args.getLastArg(OPT_fpcc_struct_return, OPT_freg_struct_return, 2075e86cf8adSDimitry Andric OPT_maix_struct_return, OPT_msvr4_struct_return)) { 20765ffd83dbSDimitry Andric // TODO: We might want to consider enabling these options on AIX in the 20775ffd83dbSDimitry Andric // future. 20785ffd83dbSDimitry Andric if (T.isOSAIX()) 20795ffd83dbSDimitry Andric Diags.Report(diag::err_drv_unsupported_opt_for_target) 20805ffd83dbSDimitry Andric << A->getSpelling() << T.str(); 20815ffd83dbSDimitry Andric 2082e86cf8adSDimitry Andric const Option &O = A->getOption(); 2083e86cf8adSDimitry Andric if (O.matches(OPT_fpcc_struct_return) || 2084e86cf8adSDimitry Andric O.matches(OPT_maix_struct_return)) { 20850b57cec5SDimitry Andric Opts.setStructReturnConvention(CodeGenOptions::SRCK_OnStack); 20860b57cec5SDimitry Andric } else { 2087e86cf8adSDimitry Andric assert(O.matches(OPT_freg_struct_return) || 2088e86cf8adSDimitry Andric O.matches(OPT_msvr4_struct_return)); 20890b57cec5SDimitry Andric Opts.setStructReturnConvention(CodeGenOptions::SRCK_InRegs); 20900b57cec5SDimitry Andric } 20910b57cec5SDimitry Andric } 20920b57cec5SDimitry Andric 209306c3fb27SDimitry Andric if (Arg *A = Args.getLastArg(OPT_mxcoff_roptr)) { 2094e8d8bef9SDimitry Andric if (!T.isOSAIX()) 2095e8d8bef9SDimitry Andric Diags.Report(diag::err_drv_unsupported_opt_for_target) 2096e8d8bef9SDimitry Andric << A->getSpelling() << T.str(); 2097e8d8bef9SDimitry Andric 209806c3fb27SDimitry Andric // Since the storage mapping class is specified per csect, 209906c3fb27SDimitry Andric // without using data sections, it is less effective to use read-only 210006c3fb27SDimitry Andric // pointers. Using read-only pointers may cause other RO variables in the 210106c3fb27SDimitry Andric // same csect to become RW when the linker acts upon `-bforceimprw`; 210206c3fb27SDimitry Andric // therefore, we require that separate data sections 210306c3fb27SDimitry Andric // are used when `-mxcoff-roptr` is in effect. We respect the setting of 210406c3fb27SDimitry Andric // data-sections since we have not found reasons to do otherwise that 210506c3fb27SDimitry Andric // overcome the user surprise of not respecting the setting. 210606c3fb27SDimitry Andric if (!Args.hasFlag(OPT_fdata_sections, OPT_fno_data_sections, false)) 210706c3fb27SDimitry Andric Diags.Report(diag::err_roptr_requires_data_sections); 210806c3fb27SDimitry Andric 210906c3fb27SDimitry Andric Opts.XCOFFReadOnlyPointers = true; 2110e8d8bef9SDimitry Andric } 2111e8d8bef9SDimitry Andric 2112972a253aSDimitry Andric if (Arg *A = Args.getLastArg(OPT_mabi_EQ_quadword_atomics)) { 2113972a253aSDimitry Andric if (!T.isOSAIX() || T.isPPC32()) 2114972a253aSDimitry Andric Diags.Report(diag::err_drv_unsupported_opt_for_target) 2115972a253aSDimitry Andric << A->getSpelling() << T.str(); 2116972a253aSDimitry Andric } 2117972a253aSDimitry Andric 21180b57cec5SDimitry Andric bool NeedLocTracking = false; 21190b57cec5SDimitry Andric 21200b57cec5SDimitry Andric if (!Opts.OptRecordFile.empty()) 21210b57cec5SDimitry Andric NeedLocTracking = true; 21220b57cec5SDimitry Andric 21230b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(OPT_opt_record_passes)) { 21240b57cec5SDimitry Andric Opts.OptRecordPasses = A->getValue(); 21250b57cec5SDimitry Andric NeedLocTracking = true; 21260b57cec5SDimitry Andric } 21270b57cec5SDimitry Andric 21280b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(OPT_opt_record_format)) { 21290b57cec5SDimitry Andric Opts.OptRecordFormat = A->getValue(); 21300b57cec5SDimitry Andric NeedLocTracking = true; 21310b57cec5SDimitry Andric } 21320b57cec5SDimitry Andric 2133fe6060f1SDimitry Andric Opts.OptimizationRemark = 2134fe6060f1SDimitry Andric ParseOptimizationRemark(Diags, Args, OPT_Rpass_EQ, "pass"); 21350b57cec5SDimitry Andric 2136fe6060f1SDimitry Andric Opts.OptimizationRemarkMissed = 2137fe6060f1SDimitry Andric ParseOptimizationRemark(Diags, Args, OPT_Rpass_missed_EQ, "pass-missed"); 21380b57cec5SDimitry Andric 2139fe6060f1SDimitry Andric Opts.OptimizationRemarkAnalysis = ParseOptimizationRemark( 2140fe6060f1SDimitry Andric Diags, Args, OPT_Rpass_analysis_EQ, "pass-analysis"); 2141fe6060f1SDimitry Andric 2142fe6060f1SDimitry Andric NeedLocTracking |= Opts.OptimizationRemark.hasValidPattern() || 2143fe6060f1SDimitry Andric Opts.OptimizationRemarkMissed.hasValidPattern() || 2144fe6060f1SDimitry Andric Opts.OptimizationRemarkAnalysis.hasValidPattern(); 21450b57cec5SDimitry Andric 21460b57cec5SDimitry Andric bool UsingSampleProfile = !Opts.SampleProfileFile.empty(); 214706c3fb27SDimitry Andric bool UsingProfile = 214806c3fb27SDimitry Andric UsingSampleProfile || !Opts.ProfileInstrumentUsePath.empty(); 21490b57cec5SDimitry Andric 21500b57cec5SDimitry Andric if (Opts.DiagnosticsWithHotness && !UsingProfile && 21510b57cec5SDimitry Andric // An IR file will contain PGO as metadata 2152a7dea167SDimitry Andric IK.getLanguage() != Language::LLVM_IR) 21530b57cec5SDimitry Andric Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo) 21540b57cec5SDimitry Andric << "-fdiagnostics-show-hotness"; 21550b57cec5SDimitry Andric 2156e8d8bef9SDimitry Andric // Parse remarks hotness threshold. Valid value is either integer or 'auto'. 2157e8d8bef9SDimitry Andric if (auto *arg = 2158e8d8bef9SDimitry Andric Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) { 2159e8d8bef9SDimitry Andric auto ResultOrErr = 2160e8d8bef9SDimitry Andric llvm::remarks::parseHotnessThresholdOption(arg->getValue()); 2161e8d8bef9SDimitry Andric 2162e8d8bef9SDimitry Andric if (!ResultOrErr) { 2163e8d8bef9SDimitry Andric Diags.Report(diag::err_drv_invalid_diagnotics_hotness_threshold) 2164e8d8bef9SDimitry Andric << "-fdiagnostics-hotness-threshold="; 2165e8d8bef9SDimitry Andric } else { 2166e8d8bef9SDimitry Andric Opts.DiagnosticsHotnessThreshold = *ResultOrErr; 216781ad6265SDimitry Andric if ((!Opts.DiagnosticsHotnessThreshold || 2168bdd1243dSDimitry Andric *Opts.DiagnosticsHotnessThreshold > 0) && 2169e8d8bef9SDimitry Andric !UsingProfile) 21700b57cec5SDimitry Andric Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo) 21710b57cec5SDimitry Andric << "-fdiagnostics-hotness-threshold="; 2172e8d8bef9SDimitry Andric } 2173e8d8bef9SDimitry Andric } 21740b57cec5SDimitry Andric 217581ad6265SDimitry Andric if (auto *arg = 217681ad6265SDimitry Andric Args.getLastArg(options::OPT_fdiagnostics_misexpect_tolerance_EQ)) { 217781ad6265SDimitry Andric auto ResultOrErr = parseToleranceOption(arg->getValue()); 217881ad6265SDimitry Andric 217981ad6265SDimitry Andric if (!ResultOrErr) { 218081ad6265SDimitry Andric Diags.Report(diag::err_drv_invalid_diagnotics_misexpect_tolerance) 218181ad6265SDimitry Andric << "-fdiagnostics-misexpect-tolerance="; 218281ad6265SDimitry Andric } else { 218381ad6265SDimitry Andric Opts.DiagnosticsMisExpectTolerance = *ResultOrErr; 218481ad6265SDimitry Andric if ((!Opts.DiagnosticsMisExpectTolerance || 2185bdd1243dSDimitry Andric *Opts.DiagnosticsMisExpectTolerance > 0) && 218681ad6265SDimitry Andric !UsingProfile) 218781ad6265SDimitry Andric Diags.Report(diag::warn_drv_diagnostics_misexpect_requires_pgo) 218881ad6265SDimitry Andric << "-fdiagnostics-misexpect-tolerance="; 218981ad6265SDimitry Andric } 219081ad6265SDimitry Andric } 219181ad6265SDimitry Andric 21920b57cec5SDimitry Andric // If the user requested to use a sample profile for PGO, then the 21930b57cec5SDimitry Andric // backend will need to track source location information so the profile 21940b57cec5SDimitry Andric // can be incorporated into the IR. 21950b57cec5SDimitry Andric if (UsingSampleProfile) 21960b57cec5SDimitry Andric NeedLocTracking = true; 21970b57cec5SDimitry Andric 2198fe6060f1SDimitry Andric if (!Opts.StackUsageOutput.empty()) 2199fe6060f1SDimitry Andric NeedLocTracking = true; 2200fe6060f1SDimitry Andric 22010b57cec5SDimitry Andric // If the user requested a flag that requires source locations available in 22020b57cec5SDimitry Andric // the backend, make sure that the backend tracks source location information. 220306c3fb27SDimitry Andric if (NeedLocTracking && 220406c3fb27SDimitry Andric Opts.getDebugInfo() == llvm::codegenoptions::NoDebugInfo) 220506c3fb27SDimitry Andric Opts.setDebugInfo(llvm::codegenoptions::LocTrackingOnly); 22060b57cec5SDimitry Andric 22070b57cec5SDimitry Andric // Parse -fsanitize-recover= arguments. 22080b57cec5SDimitry Andric // FIXME: Report unrecoverable sanitizers incorrectly specified here. 22090b57cec5SDimitry Andric parseSanitizerKinds("-fsanitize-recover=", 22100b57cec5SDimitry Andric Args.getAllArgValues(OPT_fsanitize_recover_EQ), Diags, 22110b57cec5SDimitry Andric Opts.SanitizeRecover); 22120b57cec5SDimitry Andric parseSanitizerKinds("-fsanitize-trap=", 22130b57cec5SDimitry Andric Args.getAllArgValues(OPT_fsanitize_trap_EQ), Diags, 22140b57cec5SDimitry Andric Opts.SanitizeTrap); 22150b57cec5SDimitry Andric 22160b57cec5SDimitry Andric Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true); 22170b57cec5SDimitry Andric 22180fca6ea1SDimitry Andric if (!LangOpts->CUDAIsDevice) 22190fca6ea1SDimitry Andric parsePointerAuthOptions(Opts.PointerAuth, *LangOpts, T, Diags); 22200fca6ea1SDimitry Andric 2221d409305fSDimitry Andric if (Args.hasArg(options::OPT_ffinite_loops)) 2222d409305fSDimitry Andric Opts.FiniteLoops = CodeGenOptions::FiniteLoopsKind::Always; 2223d409305fSDimitry Andric else if (Args.hasArg(options::OPT_fno_finite_loops)) 2224d409305fSDimitry Andric Opts.FiniteLoops = CodeGenOptions::FiniteLoopsKind::Never; 2225fe6060f1SDimitry Andric 222681ad6265SDimitry Andric Opts.EmitIEEENaNCompliantInsts = Args.hasFlag( 222781ad6265SDimitry Andric options::OPT_mamdgpu_ieee, options::OPT_mno_amdgpu_ieee, true); 2228fe6060f1SDimitry Andric if (!Opts.EmitIEEENaNCompliantInsts && !LangOptsRef.NoHonorNaNs) 2229fe6060f1SDimitry Andric Diags.Report(diag::err_drv_amdgpu_ieee_without_no_honor_nans); 2230fe6060f1SDimitry Andric 2231fe6060f1SDimitry Andric return Diags.getNumErrors() == NumErrorsBefore; 22320b57cec5SDimitry Andric } 22330b57cec5SDimitry Andric 22345f757f3fSDimitry Andric static void GenerateDependencyOutputArgs(const DependencyOutputOptions &Opts, 22355f757f3fSDimitry Andric ArgumentConsumer Consumer) { 2236fe6060f1SDimitry Andric const DependencyOutputOptions &DependencyOutputOpts = Opts; 223706c3fb27SDimitry Andric #define DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING(...) \ 22385f757f3fSDimitry Andric GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__) 2239fe6060f1SDimitry Andric #include "clang/Driver/Options.inc" 2240fe6060f1SDimitry Andric #undef DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING 2241fe6060f1SDimitry Andric 2242fe6060f1SDimitry Andric if (Opts.ShowIncludesDest != ShowIncludesDestination::None) 22435f757f3fSDimitry Andric GenerateArg(Consumer, OPT_show_includes); 2244fe6060f1SDimitry Andric 2245fe6060f1SDimitry Andric for (const auto &Dep : Opts.ExtraDeps) { 2246fe6060f1SDimitry Andric switch (Dep.second) { 2247fe6060f1SDimitry Andric case EDK_SanitizeIgnorelist: 2248fe6060f1SDimitry Andric // Sanitizer ignorelist arguments are generated from LanguageOptions. 2249fe6060f1SDimitry Andric continue; 2250fe6060f1SDimitry Andric case EDK_ModuleFile: 2251fe6060f1SDimitry Andric // Module file arguments are generated from FrontendOptions and 2252fe6060f1SDimitry Andric // HeaderSearchOptions. 2253fe6060f1SDimitry Andric continue; 2254fe6060f1SDimitry Andric case EDK_ProfileList: 2255fe6060f1SDimitry Andric // Profile list arguments are generated from LanguageOptions via the 2256fe6060f1SDimitry Andric // marshalling infrastructure. 2257fe6060f1SDimitry Andric continue; 2258fe6060f1SDimitry Andric case EDK_DepFileEntry: 22595f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fdepfile_entry, Dep.first); 2260fe6060f1SDimitry Andric break; 2261fe6060f1SDimitry Andric } 2262fe6060f1SDimitry Andric } 2263fe6060f1SDimitry Andric } 2264fe6060f1SDimitry Andric 2265fe6060f1SDimitry Andric static bool ParseDependencyOutputArgs(DependencyOutputOptions &Opts, 2266fe6060f1SDimitry Andric ArgList &Args, DiagnosticsEngine &Diags, 2267fe6060f1SDimitry Andric frontend::ActionKind Action, 2268fe6060f1SDimitry Andric bool ShowLineMarkers) { 2269fe6060f1SDimitry Andric unsigned NumErrorsBefore = Diags.getNumErrors(); 2270fe6060f1SDimitry Andric 2271fe6060f1SDimitry Andric DependencyOutputOptions &DependencyOutputOpts = Opts; 227206c3fb27SDimitry Andric #define DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING(...) \ 227306c3fb27SDimitry Andric PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__) 2274fe6060f1SDimitry Andric #include "clang/Driver/Options.inc" 2275fe6060f1SDimitry Andric #undef DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING 2276fe6060f1SDimitry Andric 22770b57cec5SDimitry Andric if (Args.hasArg(OPT_show_includes)) { 22780b57cec5SDimitry Andric // Writing both /showIncludes and preprocessor output to stdout 22790b57cec5SDimitry Andric // would produce interleaved output, so use stderr for /showIncludes. 22800b57cec5SDimitry Andric // This behaves the same as cl.exe, when /E, /EP or /P are passed. 2281fe6060f1SDimitry Andric if (Action == frontend::PrintPreprocessedInput || !ShowLineMarkers) 22820b57cec5SDimitry Andric Opts.ShowIncludesDest = ShowIncludesDestination::Stderr; 22830b57cec5SDimitry Andric else 22840b57cec5SDimitry Andric Opts.ShowIncludesDest = ShowIncludesDestination::Stdout; 22850b57cec5SDimitry Andric } else { 22860b57cec5SDimitry Andric Opts.ShowIncludesDest = ShowIncludesDestination::None; 22870b57cec5SDimitry Andric } 2288fe6060f1SDimitry Andric 2289fe6060f1SDimitry Andric // Add sanitizer ignorelists as extra dependencies. 22900b57cec5SDimitry Andric // They won't be discovered by the regular preprocessor, so 22910b57cec5SDimitry Andric // we let make / ninja to know about this implicit dependency. 2292fe6060f1SDimitry Andric if (!Args.hasArg(OPT_fno_sanitize_ignorelist)) { 2293fe6060f1SDimitry Andric for (const auto *A : Args.filtered(OPT_fsanitize_ignorelist_EQ)) { 2294480093f4SDimitry Andric StringRef Val = A->getValue(); 2295349cc55cSDimitry Andric if (!Val.contains('=')) 2296fe6060f1SDimitry Andric Opts.ExtraDeps.emplace_back(std::string(Val), EDK_SanitizeIgnorelist); 2297480093f4SDimitry Andric } 2298480093f4SDimitry Andric if (Opts.IncludeSystemHeaders) { 2299fe6060f1SDimitry Andric for (const auto *A : Args.filtered(OPT_fsanitize_system_ignorelist_EQ)) { 2300480093f4SDimitry Andric StringRef Val = A->getValue(); 2301349cc55cSDimitry Andric if (!Val.contains('=')) 2302fe6060f1SDimitry Andric Opts.ExtraDeps.emplace_back(std::string(Val), EDK_SanitizeIgnorelist); 2303480093f4SDimitry Andric } 2304480093f4SDimitry Andric } 2305480093f4SDimitry Andric } 2306480093f4SDimitry Andric 2307e8d8bef9SDimitry Andric // -fprofile-list= dependencies. 2308e8d8bef9SDimitry Andric for (const auto &Filename : Args.getAllArgValues(OPT_fprofile_list_EQ)) 2309fe6060f1SDimitry Andric Opts.ExtraDeps.emplace_back(Filename, EDK_ProfileList); 2310e8d8bef9SDimitry Andric 2311480093f4SDimitry Andric // Propagate the extra dependencies. 2312fe6060f1SDimitry Andric for (const auto *A : Args.filtered(OPT_fdepfile_entry)) 2313fe6060f1SDimitry Andric Opts.ExtraDeps.emplace_back(A->getValue(), EDK_DepFileEntry); 2314480093f4SDimitry Andric 23150b57cec5SDimitry Andric // Only the -fmodule-file=<file> form. 23160b57cec5SDimitry Andric for (const auto *A : Args.filtered(OPT_fmodule_file)) { 23170b57cec5SDimitry Andric StringRef Val = A->getValue(); 2318349cc55cSDimitry Andric if (!Val.contains('=')) 2319fe6060f1SDimitry Andric Opts.ExtraDeps.emplace_back(std::string(Val), EDK_ModuleFile); 23200b57cec5SDimitry Andric } 2321fe6060f1SDimitry Andric 2322bdd1243dSDimitry Andric // Check for invalid combinations of header-include-format 2323bdd1243dSDimitry Andric // and header-include-filtering. 2324bdd1243dSDimitry Andric if ((Opts.HeaderIncludeFormat == HIFMT_Textual && 2325bdd1243dSDimitry Andric Opts.HeaderIncludeFiltering != HIFIL_None) || 2326bdd1243dSDimitry Andric (Opts.HeaderIncludeFormat == HIFMT_JSON && 2327bdd1243dSDimitry Andric Opts.HeaderIncludeFiltering != HIFIL_Only_Direct_System)) 2328bdd1243dSDimitry Andric Diags.Report(diag::err_drv_print_header_env_var_combination_cc1) 2329bdd1243dSDimitry Andric << Args.getLastArg(OPT_header_include_format_EQ)->getValue() 2330bdd1243dSDimitry Andric << Args.getLastArg(OPT_header_include_filtering_EQ)->getValue(); 2331bdd1243dSDimitry Andric 2332fe6060f1SDimitry Andric return Diags.getNumErrors() == NumErrorsBefore; 23330b57cec5SDimitry Andric } 23340b57cec5SDimitry Andric 23350b57cec5SDimitry Andric static bool parseShowColorsArgs(const ArgList &Args, bool DefaultColor) { 23360b57cec5SDimitry Andric // Color diagnostics default to auto ("on" if terminal supports) in the driver 23370b57cec5SDimitry Andric // but default to off in cc1, needing an explicit OPT_fdiagnostics_color. 23380b57cec5SDimitry Andric // Support both clang's -f[no-]color-diagnostics and gcc's 23390b57cec5SDimitry Andric // -f[no-]diagnostics-colors[=never|always|auto]. 23400b57cec5SDimitry Andric enum { 23410b57cec5SDimitry Andric Colors_On, 23420b57cec5SDimitry Andric Colors_Off, 23430b57cec5SDimitry Andric Colors_Auto 23440b57cec5SDimitry Andric } ShowColors = DefaultColor ? Colors_Auto : Colors_Off; 23450b57cec5SDimitry Andric for (auto *A : Args) { 23460b57cec5SDimitry Andric const Option &O = A->getOption(); 234781ad6265SDimitry Andric if (O.matches(options::OPT_fcolor_diagnostics)) { 23480b57cec5SDimitry Andric ShowColors = Colors_On; 234981ad6265SDimitry Andric } else if (O.matches(options::OPT_fno_color_diagnostics)) { 23500b57cec5SDimitry Andric ShowColors = Colors_Off; 23510b57cec5SDimitry Andric } else if (O.matches(options::OPT_fdiagnostics_color_EQ)) { 23520b57cec5SDimitry Andric StringRef Value(A->getValue()); 23530b57cec5SDimitry Andric if (Value == "always") 23540b57cec5SDimitry Andric ShowColors = Colors_On; 23550b57cec5SDimitry Andric else if (Value == "never") 23560b57cec5SDimitry Andric ShowColors = Colors_Off; 23570b57cec5SDimitry Andric else if (Value == "auto") 23580b57cec5SDimitry Andric ShowColors = Colors_Auto; 23590b57cec5SDimitry Andric } 23600b57cec5SDimitry Andric } 23610b57cec5SDimitry Andric return ShowColors == Colors_On || 23620b57cec5SDimitry Andric (ShowColors == Colors_Auto && 23630b57cec5SDimitry Andric llvm::sys::Process::StandardErrHasColors()); 23640b57cec5SDimitry Andric } 23650b57cec5SDimitry Andric 23660b57cec5SDimitry Andric static bool checkVerifyPrefixes(const std::vector<std::string> &VerifyPrefixes, 2367e8d8bef9SDimitry Andric DiagnosticsEngine &Diags) { 23680b57cec5SDimitry Andric bool Success = true; 23690b57cec5SDimitry Andric for (const auto &Prefix : VerifyPrefixes) { 23700b57cec5SDimitry Andric // Every prefix must start with a letter and contain only alphanumeric 23710b57cec5SDimitry Andric // characters, hyphens, and underscores. 23720b57cec5SDimitry Andric auto BadChar = llvm::find_if(Prefix, [](char C) { 23730b57cec5SDimitry Andric return !isAlphanumeric(C) && C != '-' && C != '_'; 23740b57cec5SDimitry Andric }); 23750b57cec5SDimitry Andric if (BadChar != Prefix.end() || !isLetter(Prefix[0])) { 23760b57cec5SDimitry Andric Success = false; 2377e8d8bef9SDimitry Andric Diags.Report(diag::err_drv_invalid_value) << "-verify=" << Prefix; 2378e8d8bef9SDimitry Andric Diags.Report(diag::note_drv_verify_prefix_spelling); 23790b57cec5SDimitry Andric } 23800b57cec5SDimitry Andric } 2381e8d8bef9SDimitry Andric return Success; 23820b57cec5SDimitry Andric } 2383e8d8bef9SDimitry Andric 2384fe6060f1SDimitry Andric static void GenerateFileSystemArgs(const FileSystemOptions &Opts, 23855f757f3fSDimitry Andric ArgumentConsumer Consumer) { 2386fe6060f1SDimitry Andric const FileSystemOptions &FileSystemOpts = Opts; 2387e8d8bef9SDimitry Andric 238806c3fb27SDimitry Andric #define FILE_SYSTEM_OPTION_WITH_MARSHALLING(...) \ 23895f757f3fSDimitry Andric GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__) 2390e8d8bef9SDimitry Andric #include "clang/Driver/Options.inc" 2391fe6060f1SDimitry Andric #undef FILE_SYSTEM_OPTION_WITH_MARSHALLING 2392fe6060f1SDimitry Andric } 2393e8d8bef9SDimitry Andric 2394fe6060f1SDimitry Andric static bool ParseFileSystemArgs(FileSystemOptions &Opts, const ArgList &Args, 2395fe6060f1SDimitry Andric DiagnosticsEngine &Diags) { 2396fe6060f1SDimitry Andric unsigned NumErrorsBefore = Diags.getNumErrors(); 2397fe6060f1SDimitry Andric 2398fe6060f1SDimitry Andric FileSystemOptions &FileSystemOpts = Opts; 2399fe6060f1SDimitry Andric 240006c3fb27SDimitry Andric #define FILE_SYSTEM_OPTION_WITH_MARSHALLING(...) \ 240106c3fb27SDimitry Andric PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__) 2402fe6060f1SDimitry Andric #include "clang/Driver/Options.inc" 2403fe6060f1SDimitry Andric #undef FILE_SYSTEM_OPTION_WITH_MARSHALLING 2404fe6060f1SDimitry Andric 2405fe6060f1SDimitry Andric return Diags.getNumErrors() == NumErrorsBefore; 2406fe6060f1SDimitry Andric } 2407fe6060f1SDimitry Andric 2408fe6060f1SDimitry Andric static void GenerateMigratorArgs(const MigratorOptions &Opts, 24095f757f3fSDimitry Andric ArgumentConsumer Consumer) { 2410fe6060f1SDimitry Andric const MigratorOptions &MigratorOpts = Opts; 241106c3fb27SDimitry Andric #define MIGRATOR_OPTION_WITH_MARSHALLING(...) \ 24125f757f3fSDimitry Andric GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__) 2413fe6060f1SDimitry Andric #include "clang/Driver/Options.inc" 2414fe6060f1SDimitry Andric #undef MIGRATOR_OPTION_WITH_MARSHALLING 2415fe6060f1SDimitry Andric } 2416fe6060f1SDimitry Andric 2417fe6060f1SDimitry Andric static bool ParseMigratorArgs(MigratorOptions &Opts, const ArgList &Args, 2418fe6060f1SDimitry Andric DiagnosticsEngine &Diags) { 2419fe6060f1SDimitry Andric unsigned NumErrorsBefore = Diags.getNumErrors(); 2420fe6060f1SDimitry Andric 2421fe6060f1SDimitry Andric MigratorOptions &MigratorOpts = Opts; 2422fe6060f1SDimitry Andric 242306c3fb27SDimitry Andric #define MIGRATOR_OPTION_WITH_MARSHALLING(...) \ 242406c3fb27SDimitry Andric PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__) 2425fe6060f1SDimitry Andric #include "clang/Driver/Options.inc" 2426fe6060f1SDimitry Andric #undef MIGRATOR_OPTION_WITH_MARSHALLING 2427fe6060f1SDimitry Andric 2428fe6060f1SDimitry Andric return Diags.getNumErrors() == NumErrorsBefore; 2429fe6060f1SDimitry Andric } 2430fe6060f1SDimitry Andric 24315f757f3fSDimitry Andric void CompilerInvocationBase::GenerateDiagnosticArgs( 24325f757f3fSDimitry Andric const DiagnosticOptions &Opts, ArgumentConsumer Consumer, 24335f757f3fSDimitry Andric bool DefaultDiagColor) { 2434fe6060f1SDimitry Andric const DiagnosticOptions *DiagnosticOpts = &Opts; 243506c3fb27SDimitry Andric #define DIAG_OPTION_WITH_MARSHALLING(...) \ 24365f757f3fSDimitry Andric GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__) 2437fe6060f1SDimitry Andric #include "clang/Driver/Options.inc" 2438fe6060f1SDimitry Andric #undef DIAG_OPTION_WITH_MARSHALLING 2439fe6060f1SDimitry Andric 2440fe6060f1SDimitry Andric if (!Opts.DiagnosticSerializationFile.empty()) 24415f757f3fSDimitry Andric GenerateArg(Consumer, OPT_diagnostic_serialized_file, 24425f757f3fSDimitry Andric Opts.DiagnosticSerializationFile); 2443fe6060f1SDimitry Andric 2444fe6060f1SDimitry Andric if (Opts.ShowColors) 24455f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fcolor_diagnostics); 2446fe6060f1SDimitry Andric 2447fe6060f1SDimitry Andric if (Opts.VerifyDiagnostics && 2448fe6060f1SDimitry Andric llvm::is_contained(Opts.VerifyPrefixes, "expected")) 24495f757f3fSDimitry Andric GenerateArg(Consumer, OPT_verify); 2450fe6060f1SDimitry Andric 2451fe6060f1SDimitry Andric for (const auto &Prefix : Opts.VerifyPrefixes) 2452fe6060f1SDimitry Andric if (Prefix != "expected") 24535f757f3fSDimitry Andric GenerateArg(Consumer, OPT_verify_EQ, Prefix); 2454fe6060f1SDimitry Andric 2455fe6060f1SDimitry Andric DiagnosticLevelMask VIU = Opts.getVerifyIgnoreUnexpected(); 2456fe6060f1SDimitry Andric if (VIU == DiagnosticLevelMask::None) { 2457fe6060f1SDimitry Andric // This is the default, don't generate anything. 2458fe6060f1SDimitry Andric } else if (VIU == DiagnosticLevelMask::All) { 24595f757f3fSDimitry Andric GenerateArg(Consumer, OPT_verify_ignore_unexpected); 2460fe6060f1SDimitry Andric } else { 2461fe6060f1SDimitry Andric if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Note) != 0) 24625f757f3fSDimitry Andric GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "note"); 2463fe6060f1SDimitry Andric if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Remark) != 0) 24645f757f3fSDimitry Andric GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "remark"); 2465fe6060f1SDimitry Andric if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Warning) != 0) 24665f757f3fSDimitry Andric GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "warning"); 2467fe6060f1SDimitry Andric if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Error) != 0) 24685f757f3fSDimitry Andric GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "error"); 2469fe6060f1SDimitry Andric } 2470fe6060f1SDimitry Andric 2471fe6060f1SDimitry Andric for (const auto &Warning : Opts.Warnings) { 2472fe6060f1SDimitry Andric // This option is automatically generated from UndefPrefixes. 2473fe6060f1SDimitry Andric if (Warning == "undef-prefix") 2474fe6060f1SDimitry Andric continue; 24750fca6ea1SDimitry Andric // This option is automatically generated from CheckConstexprFunctionBodies. 24760fca6ea1SDimitry Andric if (Warning == "invalid-constexpr" || Warning == "no-invalid-constexpr") 24770fca6ea1SDimitry Andric continue; 24785f757f3fSDimitry Andric Consumer(StringRef("-W") + Warning); 2479fe6060f1SDimitry Andric } 2480fe6060f1SDimitry Andric 2481fe6060f1SDimitry Andric for (const auto &Remark : Opts.Remarks) { 2482fe6060f1SDimitry Andric // These arguments are generated from OptimizationRemark fields of 2483fe6060f1SDimitry Andric // CodeGenOptions. 2484fe6060f1SDimitry Andric StringRef IgnoredRemarks[] = {"pass", "no-pass", 2485fe6060f1SDimitry Andric "pass-analysis", "no-pass-analysis", 2486fe6060f1SDimitry Andric "pass-missed", "no-pass-missed"}; 2487fe6060f1SDimitry Andric if (llvm::is_contained(IgnoredRemarks, Remark)) 2488fe6060f1SDimitry Andric continue; 2489fe6060f1SDimitry Andric 24905f757f3fSDimitry Andric Consumer(StringRef("-R") + Remark); 2491fe6060f1SDimitry Andric } 24920b57cec5SDimitry Andric } 24930b57cec5SDimitry Andric 2494349cc55cSDimitry Andric std::unique_ptr<DiagnosticOptions> 2495349cc55cSDimitry Andric clang::CreateAndPopulateDiagOpts(ArrayRef<const char *> Argv) { 2496349cc55cSDimitry Andric auto DiagOpts = std::make_unique<DiagnosticOptions>(); 2497349cc55cSDimitry Andric unsigned MissingArgIndex, MissingArgCount; 2498349cc55cSDimitry Andric InputArgList Args = getDriverOptTable().ParseArgs( 2499349cc55cSDimitry Andric Argv.slice(1), MissingArgIndex, MissingArgCount); 250006c3fb27SDimitry Andric 250106c3fb27SDimitry Andric bool ShowColors = true; 250206c3fb27SDimitry Andric if (std::optional<std::string> NoColor = 250306c3fb27SDimitry Andric llvm::sys::Process::GetEnv("NO_COLOR"); 250406c3fb27SDimitry Andric NoColor && !NoColor->empty()) { 250506c3fb27SDimitry Andric // If the user set the NO_COLOR environment variable, we'll honor that 250606c3fb27SDimitry Andric // unless the command line overrides it. 250706c3fb27SDimitry Andric ShowColors = false; 250806c3fb27SDimitry Andric } 250906c3fb27SDimitry Andric 2510349cc55cSDimitry Andric // We ignore MissingArgCount and the return value of ParseDiagnosticArgs. 2511349cc55cSDimitry Andric // Any errors that would be diagnosed here will also be diagnosed later, 2512349cc55cSDimitry Andric // when the DiagnosticsEngine actually exists. 251306c3fb27SDimitry Andric (void)ParseDiagnosticArgs(*DiagOpts, Args, /*Diags=*/nullptr, ShowColors); 2514349cc55cSDimitry Andric return DiagOpts; 2515349cc55cSDimitry Andric } 2516349cc55cSDimitry Andric 25170b57cec5SDimitry Andric bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, 25180b57cec5SDimitry Andric DiagnosticsEngine *Diags, 25195ffd83dbSDimitry Andric bool DefaultDiagColor) { 2520bdd1243dSDimitry Andric std::optional<DiagnosticsEngine> IgnoringDiags; 2521e8d8bef9SDimitry Andric if (!Diags) { 2522e8d8bef9SDimitry Andric IgnoringDiags.emplace(new DiagnosticIDs(), new DiagnosticOptions(), 2523e8d8bef9SDimitry Andric new IgnoringDiagConsumer()); 2524e8d8bef9SDimitry Andric Diags = &*IgnoringDiags; 2525e8d8bef9SDimitry Andric } 2526e8d8bef9SDimitry Andric 2527fe6060f1SDimitry Andric unsigned NumErrorsBefore = Diags->getNumErrors(); 2528fe6060f1SDimitry Andric 2529e8d8bef9SDimitry Andric // The key paths of diagnostic options defined in Options.td start with 2530e8d8bef9SDimitry Andric // "DiagnosticOpts->". Let's provide the expected variable name and type. 2531e8d8bef9SDimitry Andric DiagnosticOptions *DiagnosticOpts = &Opts; 25320b57cec5SDimitry Andric 253306c3fb27SDimitry Andric #define DIAG_OPTION_WITH_MARSHALLING(...) \ 253406c3fb27SDimitry Andric PARSE_OPTION_WITH_MARSHALLING(Args, *Diags, __VA_ARGS__) 2535e8d8bef9SDimitry Andric #include "clang/Driver/Options.inc" 2536e8d8bef9SDimitry Andric #undef DIAG_OPTION_WITH_MARSHALLING 2537e8d8bef9SDimitry Andric 2538e8d8bef9SDimitry Andric llvm::sys::Process::UseANSIEscapeCodes(Opts.UseANSIEscapeCodes); 2539e8d8bef9SDimitry Andric 25400b57cec5SDimitry Andric if (Arg *A = 25410b57cec5SDimitry Andric Args.getLastArg(OPT_diagnostic_serialized_file, OPT__serialize_diags)) 25420b57cec5SDimitry Andric Opts.DiagnosticSerializationFile = A->getValue(); 25430b57cec5SDimitry Andric Opts.ShowColors = parseShowColorsArgs(Args, DefaultDiagColor); 25440b57cec5SDimitry Andric 25450b57cec5SDimitry Andric Opts.VerifyDiagnostics = Args.hasArg(OPT_verify) || Args.hasArg(OPT_verify_EQ); 2546fe6060f1SDimitry Andric Opts.VerifyPrefixes = Args.getAllArgValues(OPT_verify_EQ); 25470b57cec5SDimitry Andric if (Args.hasArg(OPT_verify)) 25480b57cec5SDimitry Andric Opts.VerifyPrefixes.push_back("expected"); 25490b57cec5SDimitry Andric // Keep VerifyPrefixes in its original order for the sake of diagnostics, and 25500b57cec5SDimitry Andric // then sort it to prepare for fast lookup using std::binary_search. 2551fe6060f1SDimitry Andric if (!checkVerifyPrefixes(Opts.VerifyPrefixes, *Diags)) 25520b57cec5SDimitry Andric Opts.VerifyDiagnostics = false; 25530b57cec5SDimitry Andric else 25540b57cec5SDimitry Andric llvm::sort(Opts.VerifyPrefixes); 25550b57cec5SDimitry Andric DiagnosticLevelMask DiagMask = DiagnosticLevelMask::None; 2556fe6060f1SDimitry Andric parseDiagnosticLevelMask( 2557fe6060f1SDimitry Andric "-verify-ignore-unexpected=", 2558fe6060f1SDimitry Andric Args.getAllArgValues(OPT_verify_ignore_unexpected_EQ), *Diags, DiagMask); 25590b57cec5SDimitry Andric if (Args.hasArg(OPT_verify_ignore_unexpected)) 25600b57cec5SDimitry Andric DiagMask = DiagnosticLevelMask::All; 25610b57cec5SDimitry Andric Opts.setVerifyIgnoreUnexpected(DiagMask); 25620b57cec5SDimitry Andric if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) { 25630b57cec5SDimitry Andric Diags->Report(diag::warn_ignoring_ftabstop_value) 25640b57cec5SDimitry Andric << Opts.TabStop << DiagnosticOptions::DefaultTabStop; 256506c3fb27SDimitry Andric Opts.TabStop = DiagnosticOptions::DefaultTabStop; 25660b57cec5SDimitry Andric } 25675ffd83dbSDimitry Andric 25680b57cec5SDimitry Andric addDiagnosticArgs(Args, OPT_W_Group, OPT_W_value_Group, Opts.Warnings); 25690b57cec5SDimitry Andric addDiagnosticArgs(Args, OPT_R_Group, OPT_R_value_Group, Opts.Remarks); 25700b57cec5SDimitry Andric 2571fe6060f1SDimitry Andric return Diags->getNumErrors() == NumErrorsBefore; 25720b57cec5SDimitry Andric } 25730b57cec5SDimitry Andric 25740b57cec5SDimitry Andric /// Parse the argument to the -ftest-module-file-extension 25750b57cec5SDimitry Andric /// command-line argument. 25760b57cec5SDimitry Andric /// 25770b57cec5SDimitry Andric /// \returns true on error, false on success. 25780b57cec5SDimitry Andric static bool parseTestModuleFileExtensionArg(StringRef Arg, 25790b57cec5SDimitry Andric std::string &BlockName, 25800b57cec5SDimitry Andric unsigned &MajorVersion, 25810b57cec5SDimitry Andric unsigned &MinorVersion, 25820b57cec5SDimitry Andric bool &Hashed, 25830b57cec5SDimitry Andric std::string &UserInfo) { 25840b57cec5SDimitry Andric SmallVector<StringRef, 5> Args; 25850b57cec5SDimitry Andric Arg.split(Args, ':', 5); 25860b57cec5SDimitry Andric if (Args.size() < 5) 25870b57cec5SDimitry Andric return true; 25880b57cec5SDimitry Andric 25895ffd83dbSDimitry Andric BlockName = std::string(Args[0]); 25900b57cec5SDimitry Andric if (Args[1].getAsInteger(10, MajorVersion)) return true; 25910b57cec5SDimitry Andric if (Args[2].getAsInteger(10, MinorVersion)) return true; 25920b57cec5SDimitry Andric if (Args[3].getAsInteger(2, Hashed)) return true; 25930b57cec5SDimitry Andric if (Args.size() > 4) 25945ffd83dbSDimitry Andric UserInfo = std::string(Args[4]); 25950b57cec5SDimitry Andric return false; 25960b57cec5SDimitry Andric } 25970b57cec5SDimitry Andric 2598fe6060f1SDimitry Andric /// Return a table that associates command line option specifiers with the 2599fe6060f1SDimitry Andric /// frontend action. Note: The pair {frontend::PluginAction, OPT_plugin} is 2600fe6060f1SDimitry Andric /// intentionally missing, as this case is handled separately from other 2601fe6060f1SDimitry Andric /// frontend options. 2602fe6060f1SDimitry Andric static const auto &getFrontendActionTable() { 2603fe6060f1SDimitry Andric static const std::pair<frontend::ActionKind, unsigned> Table[] = { 2604fe6060f1SDimitry Andric {frontend::ASTDeclList, OPT_ast_list}, 2605fe6060f1SDimitry Andric 2606fe6060f1SDimitry Andric {frontend::ASTDump, OPT_ast_dump_all_EQ}, 2607fe6060f1SDimitry Andric {frontend::ASTDump, OPT_ast_dump_all}, 2608fe6060f1SDimitry Andric {frontend::ASTDump, OPT_ast_dump_EQ}, 2609fe6060f1SDimitry Andric {frontend::ASTDump, OPT_ast_dump}, 2610fe6060f1SDimitry Andric {frontend::ASTDump, OPT_ast_dump_lookups}, 2611fe6060f1SDimitry Andric {frontend::ASTDump, OPT_ast_dump_decl_types}, 2612fe6060f1SDimitry Andric 2613fe6060f1SDimitry Andric {frontend::ASTPrint, OPT_ast_print}, 2614fe6060f1SDimitry Andric {frontend::ASTView, OPT_ast_view}, 2615fe6060f1SDimitry Andric {frontend::DumpCompilerOptions, OPT_compiler_options_dump}, 2616fe6060f1SDimitry Andric {frontend::DumpRawTokens, OPT_dump_raw_tokens}, 2617fe6060f1SDimitry Andric {frontend::DumpTokens, OPT_dump_tokens}, 2618fe6060f1SDimitry Andric {frontend::EmitAssembly, OPT_S}, 2619fe6060f1SDimitry Andric {frontend::EmitBC, OPT_emit_llvm_bc}, 26200fca6ea1SDimitry Andric {frontend::EmitCIR, OPT_emit_cir}, 2621fe6060f1SDimitry Andric {frontend::EmitHTML, OPT_emit_html}, 2622fe6060f1SDimitry Andric {frontend::EmitLLVM, OPT_emit_llvm}, 2623fe6060f1SDimitry Andric {frontend::EmitLLVMOnly, OPT_emit_llvm_only}, 2624fe6060f1SDimitry Andric {frontend::EmitCodeGenOnly, OPT_emit_codegen_only}, 2625fe6060f1SDimitry Andric {frontend::EmitObj, OPT_emit_obj}, 262604eeddc0SDimitry Andric {frontend::ExtractAPI, OPT_extract_api}, 2627fe6060f1SDimitry Andric 2628fe6060f1SDimitry Andric {frontend::FixIt, OPT_fixit_EQ}, 2629fe6060f1SDimitry Andric {frontend::FixIt, OPT_fixit}, 2630fe6060f1SDimitry Andric 2631fe6060f1SDimitry Andric {frontend::GenerateModule, OPT_emit_module}, 2632fe6060f1SDimitry Andric {frontend::GenerateModuleInterface, OPT_emit_module_interface}, 26330fca6ea1SDimitry Andric {frontend::GenerateReducedModuleInterface, 26340fca6ea1SDimitry Andric OPT_emit_reduced_module_interface}, 263581ad6265SDimitry Andric {frontend::GenerateHeaderUnit, OPT_emit_header_unit}, 2636fe6060f1SDimitry Andric {frontend::GeneratePCH, OPT_emit_pch}, 2637fe6060f1SDimitry Andric {frontend::GenerateInterfaceStubs, OPT_emit_interface_stubs}, 2638fe6060f1SDimitry Andric {frontend::InitOnly, OPT_init_only}, 2639fe6060f1SDimitry Andric {frontend::ParseSyntaxOnly, OPT_fsyntax_only}, 2640fe6060f1SDimitry Andric {frontend::ModuleFileInfo, OPT_module_file_info}, 2641fe6060f1SDimitry Andric {frontend::VerifyPCH, OPT_verify_pch}, 2642fe6060f1SDimitry Andric {frontend::PrintPreamble, OPT_print_preamble}, 2643fe6060f1SDimitry Andric {frontend::PrintPreprocessedInput, OPT_E}, 2644fe6060f1SDimitry Andric {frontend::TemplightDump, OPT_templight_dump}, 2645fe6060f1SDimitry Andric {frontend::RewriteMacros, OPT_rewrite_macros}, 2646fe6060f1SDimitry Andric {frontend::RewriteObjC, OPT_rewrite_objc}, 2647fe6060f1SDimitry Andric {frontend::RewriteTest, OPT_rewrite_test}, 2648fe6060f1SDimitry Andric {frontend::RunAnalysis, OPT_analyze}, 2649fe6060f1SDimitry Andric {frontend::MigrateSource, OPT_migrate}, 2650fe6060f1SDimitry Andric {frontend::RunPreprocessorOnly, OPT_Eonly}, 2651fe6060f1SDimitry Andric {frontend::PrintDependencyDirectivesSourceMinimizerOutput, 2652fe6060f1SDimitry Andric OPT_print_dependency_directives_minimized_source}, 2653fe6060f1SDimitry Andric }; 2654fe6060f1SDimitry Andric 2655fe6060f1SDimitry Andric return Table; 2656fe6060f1SDimitry Andric } 2657fe6060f1SDimitry Andric 2658fe6060f1SDimitry Andric /// Maps command line option to frontend action. 2659bdd1243dSDimitry Andric static std::optional<frontend::ActionKind> 2660bdd1243dSDimitry Andric getFrontendAction(OptSpecifier &Opt) { 2661fe6060f1SDimitry Andric for (const auto &ActionOpt : getFrontendActionTable()) 2662fe6060f1SDimitry Andric if (ActionOpt.second == Opt.getID()) 2663fe6060f1SDimitry Andric return ActionOpt.first; 2664fe6060f1SDimitry Andric 2665bdd1243dSDimitry Andric return std::nullopt; 2666fe6060f1SDimitry Andric } 2667fe6060f1SDimitry Andric 2668fe6060f1SDimitry Andric /// Maps frontend action to command line option. 2669bdd1243dSDimitry Andric static std::optional<OptSpecifier> 2670fe6060f1SDimitry Andric getProgramActionOpt(frontend::ActionKind ProgramAction) { 2671fe6060f1SDimitry Andric for (const auto &ActionOpt : getFrontendActionTable()) 2672fe6060f1SDimitry Andric if (ActionOpt.first == ProgramAction) 2673fe6060f1SDimitry Andric return OptSpecifier(ActionOpt.second); 2674fe6060f1SDimitry Andric 2675bdd1243dSDimitry Andric return std::nullopt; 2676fe6060f1SDimitry Andric } 2677fe6060f1SDimitry Andric 2678fe6060f1SDimitry Andric static void GenerateFrontendArgs(const FrontendOptions &Opts, 26795f757f3fSDimitry Andric ArgumentConsumer Consumer, bool IsHeader) { 2680fe6060f1SDimitry Andric const FrontendOptions &FrontendOpts = Opts; 268106c3fb27SDimitry Andric #define FRONTEND_OPTION_WITH_MARSHALLING(...) \ 26825f757f3fSDimitry Andric GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__) 2683fe6060f1SDimitry Andric #include "clang/Driver/Options.inc" 2684fe6060f1SDimitry Andric #undef FRONTEND_OPTION_WITH_MARSHALLING 2685fe6060f1SDimitry Andric 2686bdd1243dSDimitry Andric std::optional<OptSpecifier> ProgramActionOpt = 2687fe6060f1SDimitry Andric getProgramActionOpt(Opts.ProgramAction); 2688fe6060f1SDimitry Andric 2689fe6060f1SDimitry Andric // Generating a simple flag covers most frontend actions. 2690fe6060f1SDimitry Andric std::function<void()> GenerateProgramAction = [&]() { 26915f757f3fSDimitry Andric GenerateArg(Consumer, *ProgramActionOpt); 2692fe6060f1SDimitry Andric }; 2693fe6060f1SDimitry Andric 2694fe6060f1SDimitry Andric if (!ProgramActionOpt) { 2695fe6060f1SDimitry Andric // PluginAction is the only program action handled separately. 2696fe6060f1SDimitry Andric assert(Opts.ProgramAction == frontend::PluginAction && 2697fe6060f1SDimitry Andric "Frontend action without option."); 2698fe6060f1SDimitry Andric GenerateProgramAction = [&]() { 26995f757f3fSDimitry Andric GenerateArg(Consumer, OPT_plugin, Opts.ActionName); 2700fe6060f1SDimitry Andric }; 2701fe6060f1SDimitry Andric } 2702fe6060f1SDimitry Andric 2703fe6060f1SDimitry Andric // FIXME: Simplify the complex 'AST dump' command line. 2704fe6060f1SDimitry Andric if (Opts.ProgramAction == frontend::ASTDump) { 2705fe6060f1SDimitry Andric GenerateProgramAction = [&]() { 2706fe6060f1SDimitry Andric // ASTDumpLookups, ASTDumpDeclTypes and ASTDumpFilter are generated via 2707fe6060f1SDimitry Andric // marshalling infrastructure. 2708fe6060f1SDimitry Andric 2709fe6060f1SDimitry Andric if (Opts.ASTDumpFormat != ADOF_Default) { 2710fe6060f1SDimitry Andric StringRef Format; 2711fe6060f1SDimitry Andric switch (Opts.ASTDumpFormat) { 2712fe6060f1SDimitry Andric case ADOF_Default: 2713fe6060f1SDimitry Andric llvm_unreachable("Default AST dump format."); 2714fe6060f1SDimitry Andric case ADOF_JSON: 2715fe6060f1SDimitry Andric Format = "json"; 2716fe6060f1SDimitry Andric break; 2717fe6060f1SDimitry Andric } 2718fe6060f1SDimitry Andric 2719fe6060f1SDimitry Andric if (Opts.ASTDumpAll) 27205f757f3fSDimitry Andric GenerateArg(Consumer, OPT_ast_dump_all_EQ, Format); 2721fe6060f1SDimitry Andric if (Opts.ASTDumpDecls) 27225f757f3fSDimitry Andric GenerateArg(Consumer, OPT_ast_dump_EQ, Format); 2723fe6060f1SDimitry Andric } else { 2724fe6060f1SDimitry Andric if (Opts.ASTDumpAll) 27255f757f3fSDimitry Andric GenerateArg(Consumer, OPT_ast_dump_all); 2726fe6060f1SDimitry Andric if (Opts.ASTDumpDecls) 27275f757f3fSDimitry Andric GenerateArg(Consumer, OPT_ast_dump); 2728fe6060f1SDimitry Andric } 2729fe6060f1SDimitry Andric }; 2730fe6060f1SDimitry Andric } 2731fe6060f1SDimitry Andric 2732fe6060f1SDimitry Andric if (Opts.ProgramAction == frontend::FixIt && !Opts.FixItSuffix.empty()) { 2733fe6060f1SDimitry Andric GenerateProgramAction = [&]() { 27345f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fixit_EQ, Opts.FixItSuffix); 2735fe6060f1SDimitry Andric }; 2736fe6060f1SDimitry Andric } 2737fe6060f1SDimitry Andric 2738fe6060f1SDimitry Andric GenerateProgramAction(); 2739fe6060f1SDimitry Andric 2740fe6060f1SDimitry Andric for (const auto &PluginArgs : Opts.PluginArgs) { 2741fe6060f1SDimitry Andric Option Opt = getDriverOptTable().getOption(OPT_plugin_arg); 2742fe6060f1SDimitry Andric for (const auto &PluginArg : PluginArgs.second) 27435f757f3fSDimitry Andric denormalizeString(Consumer, 27445f757f3fSDimitry Andric Opt.getPrefix() + Opt.getName() + PluginArgs.first, 27455f757f3fSDimitry Andric Opt.getKind(), 0, PluginArg); 2746fe6060f1SDimitry Andric } 2747fe6060f1SDimitry Andric 2748fe6060f1SDimitry Andric for (const auto &Ext : Opts.ModuleFileExtensions) 2749fe6060f1SDimitry Andric if (auto *TestExt = dyn_cast_or_null<TestModuleFileExtension>(Ext.get())) 27505f757f3fSDimitry Andric GenerateArg(Consumer, OPT_ftest_module_file_extension_EQ, TestExt->str()); 2751fe6060f1SDimitry Andric 2752fe6060f1SDimitry Andric if (!Opts.CodeCompletionAt.FileName.empty()) 27535f757f3fSDimitry Andric GenerateArg(Consumer, OPT_code_completion_at, 27545f757f3fSDimitry Andric Opts.CodeCompletionAt.ToString()); 2755fe6060f1SDimitry Andric 2756fe6060f1SDimitry Andric for (const auto &Plugin : Opts.Plugins) 27575f757f3fSDimitry Andric GenerateArg(Consumer, OPT_load, Plugin); 2758fe6060f1SDimitry Andric 2759fe6060f1SDimitry Andric // ASTDumpDecls and ASTDumpAll already handled with ProgramAction. 2760fe6060f1SDimitry Andric 2761fe6060f1SDimitry Andric for (const auto &ModuleFile : Opts.ModuleFiles) 27625f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fmodule_file, ModuleFile); 2763fe6060f1SDimitry Andric 276481ad6265SDimitry Andric if (Opts.AuxTargetCPU) 27655f757f3fSDimitry Andric GenerateArg(Consumer, OPT_aux_target_cpu, *Opts.AuxTargetCPU); 2766fe6060f1SDimitry Andric 276781ad6265SDimitry Andric if (Opts.AuxTargetFeatures) 2768fe6060f1SDimitry Andric for (const auto &Feature : *Opts.AuxTargetFeatures) 27695f757f3fSDimitry Andric GenerateArg(Consumer, OPT_aux_target_feature, Feature); 2770fe6060f1SDimitry Andric 2771fe6060f1SDimitry Andric { 2772fe6060f1SDimitry Andric StringRef Preprocessed = Opts.DashX.isPreprocessed() ? "-cpp-output" : ""; 2773fe6060f1SDimitry Andric StringRef ModuleMap = 2774fe6060f1SDimitry Andric Opts.DashX.getFormat() == InputKind::ModuleMap ? "-module-map" : ""; 277581ad6265SDimitry Andric StringRef HeaderUnit = ""; 277681ad6265SDimitry Andric switch (Opts.DashX.getHeaderUnitKind()) { 277781ad6265SDimitry Andric case InputKind::HeaderUnit_None: 277881ad6265SDimitry Andric break; 277981ad6265SDimitry Andric case InputKind::HeaderUnit_User: 278081ad6265SDimitry Andric HeaderUnit = "-user"; 278181ad6265SDimitry Andric break; 278281ad6265SDimitry Andric case InputKind::HeaderUnit_System: 278381ad6265SDimitry Andric HeaderUnit = "-system"; 278481ad6265SDimitry Andric break; 278581ad6265SDimitry Andric case InputKind::HeaderUnit_Abs: 278681ad6265SDimitry Andric HeaderUnit = "-header-unit"; 278781ad6265SDimitry Andric break; 278881ad6265SDimitry Andric } 2789fe6060f1SDimitry Andric StringRef Header = IsHeader ? "-header" : ""; 2790fe6060f1SDimitry Andric 2791fe6060f1SDimitry Andric StringRef Lang; 2792fe6060f1SDimitry Andric switch (Opts.DashX.getLanguage()) { 2793fe6060f1SDimitry Andric case Language::C: 2794fe6060f1SDimitry Andric Lang = "c"; 2795fe6060f1SDimitry Andric break; 2796fe6060f1SDimitry Andric case Language::OpenCL: 2797fe6060f1SDimitry Andric Lang = "cl"; 2798fe6060f1SDimitry Andric break; 2799fe6060f1SDimitry Andric case Language::OpenCLCXX: 2800fe6060f1SDimitry Andric Lang = "clcpp"; 2801fe6060f1SDimitry Andric break; 2802fe6060f1SDimitry Andric case Language::CUDA: 2803fe6060f1SDimitry Andric Lang = "cuda"; 2804fe6060f1SDimitry Andric break; 2805fe6060f1SDimitry Andric case Language::HIP: 2806fe6060f1SDimitry Andric Lang = "hip"; 2807fe6060f1SDimitry Andric break; 2808fe6060f1SDimitry Andric case Language::CXX: 2809fe6060f1SDimitry Andric Lang = "c++"; 2810fe6060f1SDimitry Andric break; 2811fe6060f1SDimitry Andric case Language::ObjC: 2812fe6060f1SDimitry Andric Lang = "objective-c"; 2813fe6060f1SDimitry Andric break; 2814fe6060f1SDimitry Andric case Language::ObjCXX: 2815fe6060f1SDimitry Andric Lang = "objective-c++"; 2816fe6060f1SDimitry Andric break; 2817fe6060f1SDimitry Andric case Language::RenderScript: 2818fe6060f1SDimitry Andric Lang = "renderscript"; 2819fe6060f1SDimitry Andric break; 2820fe6060f1SDimitry Andric case Language::Asm: 2821fe6060f1SDimitry Andric Lang = "assembler-with-cpp"; 2822fe6060f1SDimitry Andric break; 2823fe6060f1SDimitry Andric case Language::Unknown: 2824fe6060f1SDimitry Andric assert(Opts.DashX.getFormat() == InputKind::Precompiled && 2825fe6060f1SDimitry Andric "Generating -x argument for unknown language (not precompiled)."); 2826fe6060f1SDimitry Andric Lang = "ast"; 2827fe6060f1SDimitry Andric break; 2828fe6060f1SDimitry Andric case Language::LLVM_IR: 2829fe6060f1SDimitry Andric Lang = "ir"; 2830fe6060f1SDimitry Andric break; 283181ad6265SDimitry Andric case Language::HLSL: 283281ad6265SDimitry Andric Lang = "hlsl"; 283381ad6265SDimitry Andric break; 28340fca6ea1SDimitry Andric case Language::CIR: 28350fca6ea1SDimitry Andric Lang = "cir"; 28360fca6ea1SDimitry Andric break; 2837fe6060f1SDimitry Andric } 2838fe6060f1SDimitry Andric 28395f757f3fSDimitry Andric GenerateArg(Consumer, OPT_x, 28405f757f3fSDimitry Andric Lang + HeaderUnit + Header + ModuleMap + Preprocessed); 2841fe6060f1SDimitry Andric } 2842fe6060f1SDimitry Andric 2843fe6060f1SDimitry Andric // OPT_INPUT has a unique class, generate it directly. 2844fe6060f1SDimitry Andric for (const auto &Input : Opts.Inputs) 28455f757f3fSDimitry Andric Consumer(Input.getFile()); 2846fe6060f1SDimitry Andric } 2847fe6060f1SDimitry Andric 2848fe6060f1SDimitry Andric static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, 2849fe6060f1SDimitry Andric DiagnosticsEngine &Diags, bool &IsHeaderFile) { 2850fe6060f1SDimitry Andric unsigned NumErrorsBefore = Diags.getNumErrors(); 2851fe6060f1SDimitry Andric 2852fe6060f1SDimitry Andric FrontendOptions &FrontendOpts = Opts; 2853fe6060f1SDimitry Andric 285406c3fb27SDimitry Andric #define FRONTEND_OPTION_WITH_MARSHALLING(...) \ 285506c3fb27SDimitry Andric PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__) 2856fe6060f1SDimitry Andric #include "clang/Driver/Options.inc" 2857fe6060f1SDimitry Andric #undef FRONTEND_OPTION_WITH_MARSHALLING 2858fe6060f1SDimitry Andric 28590b57cec5SDimitry Andric Opts.ProgramAction = frontend::ParseSyntaxOnly; 28600b57cec5SDimitry Andric if (const Arg *A = Args.getLastArg(OPT_Action_Group)) { 2861fe6060f1SDimitry Andric OptSpecifier Opt = OptSpecifier(A->getOption().getID()); 2862bdd1243dSDimitry Andric std::optional<frontend::ActionKind> ProgramAction = getFrontendAction(Opt); 2863fe6060f1SDimitry Andric assert(ProgramAction && "Option specifier not in Action_Group."); 2864fe6060f1SDimitry Andric 2865fe6060f1SDimitry Andric if (ProgramAction == frontend::ASTDump && 2866fe6060f1SDimitry Andric (Opt == OPT_ast_dump_all_EQ || Opt == OPT_ast_dump_EQ)) { 28670b57cec5SDimitry Andric unsigned Val = llvm::StringSwitch<unsigned>(A->getValue()) 28680b57cec5SDimitry Andric .CaseLower("default", ADOF_Default) 28690b57cec5SDimitry Andric .CaseLower("json", ADOF_JSON) 28700b57cec5SDimitry Andric .Default(std::numeric_limits<unsigned>::max()); 28710b57cec5SDimitry Andric 28720b57cec5SDimitry Andric if (Val != std::numeric_limits<unsigned>::max()) 28730b57cec5SDimitry Andric Opts.ASTDumpFormat = static_cast<ASTDumpOutputFormat>(Val); 28740b57cec5SDimitry Andric else { 28750b57cec5SDimitry Andric Diags.Report(diag::err_drv_invalid_value) 28760b57cec5SDimitry Andric << A->getAsString(Args) << A->getValue(); 28770b57cec5SDimitry Andric Opts.ASTDumpFormat = ADOF_Default; 28780b57cec5SDimitry Andric } 28790b57cec5SDimitry Andric } 2880fe6060f1SDimitry Andric 2881fe6060f1SDimitry Andric if (ProgramAction == frontend::FixIt && Opt == OPT_fixit_EQ) 28820b57cec5SDimitry Andric Opts.FixItSuffix = A->getValue(); 2883fe6060f1SDimitry Andric 2884fe6060f1SDimitry Andric if (ProgramAction == frontend::GenerateInterfaceStubs) { 2885a7dea167SDimitry Andric StringRef ArgStr = 2886a7dea167SDimitry Andric Args.hasArg(OPT_interface_stub_version_EQ) 2887a7dea167SDimitry Andric ? Args.getLastArgValue(OPT_interface_stub_version_EQ) 2888fe6060f1SDimitry Andric : "ifs-v1"; 2889a7dea167SDimitry Andric if (ArgStr == "experimental-yaml-elf-v1" || 2890fe6060f1SDimitry Andric ArgStr == "experimental-ifs-v1" || ArgStr == "experimental-ifs-v2" || 2891a7dea167SDimitry Andric ArgStr == "experimental-tapi-elf-v1") { 2892a7dea167SDimitry Andric std::string ErrorMessage = 2893a7dea167SDimitry Andric "Invalid interface stub format: " + ArgStr.str() + 2894a7dea167SDimitry Andric " is deprecated."; 28950b57cec5SDimitry Andric Diags.Report(diag::err_drv_invalid_value) 2896a7dea167SDimitry Andric << "Must specify a valid interface stub format type, ie: " 2897fe6060f1SDimitry Andric "-interface-stub-version=ifs-v1" 2898a7dea167SDimitry Andric << ErrorMessage; 2899fe6060f1SDimitry Andric ProgramAction = frontend::ParseSyntaxOnly; 29005f757f3fSDimitry Andric } else if (!ArgStr.starts_with("ifs-")) { 2901a7dea167SDimitry Andric std::string ErrorMessage = 2902a7dea167SDimitry Andric "Invalid interface stub format: " + ArgStr.str() + "."; 2903a7dea167SDimitry Andric Diags.Report(diag::err_drv_invalid_value) 2904a7dea167SDimitry Andric << "Must specify a valid interface stub format type, ie: " 2905fe6060f1SDimitry Andric "-interface-stub-version=ifs-v1" 2906a7dea167SDimitry Andric << ErrorMessage; 2907fe6060f1SDimitry Andric ProgramAction = frontend::ParseSyntaxOnly; 2908a7dea167SDimitry Andric } 29090b57cec5SDimitry Andric } 2910fe6060f1SDimitry Andric 2911fe6060f1SDimitry Andric Opts.ProgramAction = *ProgramAction; 29120fca6ea1SDimitry Andric 29130fca6ea1SDimitry Andric // Catch common mistakes when multiple actions are specified for cc1 (e.g. 29140fca6ea1SDimitry Andric // -S -emit-llvm means -emit-llvm while -emit-llvm -S means -S). However, to 29150fca6ea1SDimitry Andric // support driver `-c -Xclang ACTION` (-cc1 -emit-llvm file -main-file-name 29160fca6ea1SDimitry Andric // X ACTION), we suppress the error when the two actions are separated by 29170fca6ea1SDimitry Andric // -main-file-name. 29180fca6ea1SDimitry Andric // 29190fca6ea1SDimitry Andric // As an exception, accept composable -ast-dump*. 29200fca6ea1SDimitry Andric if (!A->getSpelling().starts_with("-ast-dump")) { 29210fca6ea1SDimitry Andric const Arg *SavedAction = nullptr; 29220fca6ea1SDimitry Andric for (const Arg *AA : 29230fca6ea1SDimitry Andric Args.filtered(OPT_Action_Group, OPT_main_file_name)) { 29240fca6ea1SDimitry Andric if (AA->getOption().matches(OPT_main_file_name)) { 29250fca6ea1SDimitry Andric SavedAction = nullptr; 29260fca6ea1SDimitry Andric } else if (!SavedAction) { 29270fca6ea1SDimitry Andric SavedAction = AA; 29280fca6ea1SDimitry Andric } else { 29290fca6ea1SDimitry Andric if (!A->getOption().matches(OPT_ast_dump_EQ)) 29300fca6ea1SDimitry Andric Diags.Report(diag::err_fe_invalid_multiple_actions) 29310fca6ea1SDimitry Andric << SavedAction->getSpelling() << A->getSpelling(); 29320fca6ea1SDimitry Andric break; 29330fca6ea1SDimitry Andric } 29340fca6ea1SDimitry Andric } 29350fca6ea1SDimitry Andric } 29360b57cec5SDimitry Andric } 29370b57cec5SDimitry Andric 29380b57cec5SDimitry Andric if (const Arg* A = Args.getLastArg(OPT_plugin)) { 29390b57cec5SDimitry Andric Opts.Plugins.emplace_back(A->getValue(0)); 29400b57cec5SDimitry Andric Opts.ProgramAction = frontend::PluginAction; 29410b57cec5SDimitry Andric Opts.ActionName = A->getValue(); 29420b57cec5SDimitry Andric } 29430b57cec5SDimitry Andric for (const auto *AA : Args.filtered(OPT_plugin_arg)) 29440b57cec5SDimitry Andric Opts.PluginArgs[AA->getValue(0)].emplace_back(AA->getValue(1)); 29450b57cec5SDimitry Andric 29460b57cec5SDimitry Andric for (const std::string &Arg : 29470b57cec5SDimitry Andric Args.getAllArgValues(OPT_ftest_module_file_extension_EQ)) { 29480b57cec5SDimitry Andric std::string BlockName; 29490b57cec5SDimitry Andric unsigned MajorVersion; 29500b57cec5SDimitry Andric unsigned MinorVersion; 29510b57cec5SDimitry Andric bool Hashed; 29520b57cec5SDimitry Andric std::string UserInfo; 29530b57cec5SDimitry Andric if (parseTestModuleFileExtensionArg(Arg, BlockName, MajorVersion, 29540b57cec5SDimitry Andric MinorVersion, Hashed, UserInfo)) { 29550b57cec5SDimitry Andric Diags.Report(diag::err_test_module_file_extension_format) << Arg; 29560b57cec5SDimitry Andric 29570b57cec5SDimitry Andric continue; 29580b57cec5SDimitry Andric } 29590b57cec5SDimitry Andric 29600b57cec5SDimitry Andric // Add the testing module file extension. 29610b57cec5SDimitry Andric Opts.ModuleFileExtensions.push_back( 29620b57cec5SDimitry Andric std::make_shared<TestModuleFileExtension>( 29630b57cec5SDimitry Andric BlockName, MajorVersion, MinorVersion, Hashed, UserInfo)); 29640b57cec5SDimitry Andric } 29650b57cec5SDimitry Andric 29660b57cec5SDimitry Andric if (const Arg *A = Args.getLastArg(OPT_code_completion_at)) { 29670b57cec5SDimitry Andric Opts.CodeCompletionAt = 29680b57cec5SDimitry Andric ParsedSourceLocation::FromString(A->getValue()); 29690b57cec5SDimitry Andric if (Opts.CodeCompletionAt.FileName.empty()) 29700b57cec5SDimitry Andric Diags.Report(diag::err_drv_invalid_value) 29710b57cec5SDimitry Andric << A->getAsString(Args) << A->getValue(); 29720b57cec5SDimitry Andric } 29730b57cec5SDimitry Andric 29740b57cec5SDimitry Andric Opts.Plugins = Args.getAllArgValues(OPT_load); 29750b57cec5SDimitry Andric Opts.ASTDumpDecls = Args.hasArg(OPT_ast_dump, OPT_ast_dump_EQ); 29760b57cec5SDimitry Andric Opts.ASTDumpAll = Args.hasArg(OPT_ast_dump_all, OPT_ast_dump_all_EQ); 29770b57cec5SDimitry Andric // Only the -fmodule-file=<file> form. 29780b57cec5SDimitry Andric for (const auto *A : Args.filtered(OPT_fmodule_file)) { 29790b57cec5SDimitry Andric StringRef Val = A->getValue(); 2980349cc55cSDimitry Andric if (!Val.contains('=')) 29815ffd83dbSDimitry Andric Opts.ModuleFiles.push_back(std::string(Val)); 29820b57cec5SDimitry Andric } 29835ffd83dbSDimitry Andric 29845ffd83dbSDimitry Andric if (Opts.ProgramAction != frontend::GenerateModule && Opts.IsSystemModule) 29855ffd83dbSDimitry Andric Diags.Report(diag::err_drv_argument_only_allowed_with) << "-fsystem-module" 29865ffd83dbSDimitry Andric << "-emit-module"; 29870fca6ea1SDimitry Andric if (Args.hasArg(OPT_fclangir) || Args.hasArg(OPT_emit_cir)) 29880fca6ea1SDimitry Andric Opts.UseClangIRPipeline = true; 29890b57cec5SDimitry Andric 29905ffd83dbSDimitry Andric if (Args.hasArg(OPT_aux_target_cpu)) 29915ffd83dbSDimitry Andric Opts.AuxTargetCPU = std::string(Args.getLastArgValue(OPT_aux_target_cpu)); 29925ffd83dbSDimitry Andric if (Args.hasArg(OPT_aux_target_feature)) 29935ffd83dbSDimitry Andric Opts.AuxTargetFeatures = Args.getAllArgValues(OPT_aux_target_feature); 29940b57cec5SDimitry Andric 29950b57cec5SDimitry Andric if (Opts.ARCMTAction != FrontendOptions::ARCMT_None && 29960b57cec5SDimitry Andric Opts.ObjCMTAction != FrontendOptions::ObjCMT_None) { 29970b57cec5SDimitry Andric Diags.Report(diag::err_drv_argument_not_allowed_with) 29980b57cec5SDimitry Andric << "ARC migration" << "ObjC migration"; 29990b57cec5SDimitry Andric } 30000b57cec5SDimitry Andric 3001a7dea167SDimitry Andric InputKind DashX(Language::Unknown); 30020b57cec5SDimitry Andric if (const Arg *A = Args.getLastArg(OPT_x)) { 30030b57cec5SDimitry Andric StringRef XValue = A->getValue(); 30040b57cec5SDimitry Andric 300581ad6265SDimitry Andric // Parse suffixes: 300681ad6265SDimitry Andric // '<lang>(-[{header-unit,user,system}-]header|[-module-map][-cpp-output])'. 30070b57cec5SDimitry Andric // FIXME: Supporting '<lang>-header-cpp-output' would be useful. 30080b57cec5SDimitry Andric bool Preprocessed = XValue.consume_back("-cpp-output"); 30090b57cec5SDimitry Andric bool ModuleMap = XValue.consume_back("-module-map"); 301081ad6265SDimitry Andric // Detect and consume the header indicator. 301181ad6265SDimitry Andric bool IsHeader = 301281ad6265SDimitry Andric XValue != "precompiled-header" && XValue.consume_back("-header"); 301381ad6265SDimitry Andric 301481ad6265SDimitry Andric // If we have c++-{user,system}-header, that indicates a header unit input 301581ad6265SDimitry Andric // likewise, if the user put -fmodule-header together with a header with an 301681ad6265SDimitry Andric // absolute path (header-unit-header). 301781ad6265SDimitry Andric InputKind::HeaderUnitKind HUK = InputKind::HeaderUnit_None; 301881ad6265SDimitry Andric if (IsHeader || Preprocessed) { 301981ad6265SDimitry Andric if (XValue.consume_back("-header-unit")) 302081ad6265SDimitry Andric HUK = InputKind::HeaderUnit_Abs; 302181ad6265SDimitry Andric else if (XValue.consume_back("-system")) 302281ad6265SDimitry Andric HUK = InputKind::HeaderUnit_System; 302381ad6265SDimitry Andric else if (XValue.consume_back("-user")) 302481ad6265SDimitry Andric HUK = InputKind::HeaderUnit_User; 302581ad6265SDimitry Andric } 302681ad6265SDimitry Andric 302781ad6265SDimitry Andric // The value set by this processing is an un-preprocessed source which is 302881ad6265SDimitry Andric // not intended to be a module map or header unit. 302981ad6265SDimitry Andric IsHeaderFile = IsHeader && !Preprocessed && !ModuleMap && 303081ad6265SDimitry Andric HUK == InputKind::HeaderUnit_None; 30310b57cec5SDimitry Andric 30320b57cec5SDimitry Andric // Principal languages. 30330b57cec5SDimitry Andric DashX = llvm::StringSwitch<InputKind>(XValue) 3034a7dea167SDimitry Andric .Case("c", Language::C) 3035a7dea167SDimitry Andric .Case("cl", Language::OpenCL) 3036fe6060f1SDimitry Andric .Case("clcpp", Language::OpenCLCXX) 3037a7dea167SDimitry Andric .Case("cuda", Language::CUDA) 3038a7dea167SDimitry Andric .Case("hip", Language::HIP) 3039a7dea167SDimitry Andric .Case("c++", Language::CXX) 3040a7dea167SDimitry Andric .Case("objective-c", Language::ObjC) 3041a7dea167SDimitry Andric .Case("objective-c++", Language::ObjCXX) 3042a7dea167SDimitry Andric .Case("renderscript", Language::RenderScript) 304381ad6265SDimitry Andric .Case("hlsl", Language::HLSL) 3044a7dea167SDimitry Andric .Default(Language::Unknown); 30450b57cec5SDimitry Andric 30460b57cec5SDimitry Andric // "objc[++]-cpp-output" is an acceptable synonym for 30470b57cec5SDimitry Andric // "objective-c[++]-cpp-output". 304881ad6265SDimitry Andric if (DashX.isUnknown() && Preprocessed && !IsHeaderFile && !ModuleMap && 304981ad6265SDimitry Andric HUK == InputKind::HeaderUnit_None) 30500b57cec5SDimitry Andric DashX = llvm::StringSwitch<InputKind>(XValue) 3051a7dea167SDimitry Andric .Case("objc", Language::ObjC) 3052a7dea167SDimitry Andric .Case("objc++", Language::ObjCXX) 3053a7dea167SDimitry Andric .Default(Language::Unknown); 30540b57cec5SDimitry Andric 30550b57cec5SDimitry Andric // Some special cases cannot be combined with suffixes. 305681ad6265SDimitry Andric if (DashX.isUnknown() && !Preprocessed && !IsHeaderFile && !ModuleMap && 305781ad6265SDimitry Andric HUK == InputKind::HeaderUnit_None) 30580b57cec5SDimitry Andric DashX = llvm::StringSwitch<InputKind>(XValue) 3059a7dea167SDimitry Andric .Case("cpp-output", InputKind(Language::C).getPreprocessed()) 3060a7dea167SDimitry Andric .Case("assembler-with-cpp", Language::Asm) 3061590d96feSDimitry Andric .Cases("ast", "pcm", "precompiled-header", 3062a7dea167SDimitry Andric InputKind(Language::Unknown, InputKind::Precompiled)) 3063a7dea167SDimitry Andric .Case("ir", Language::LLVM_IR) 30640fca6ea1SDimitry Andric .Case("cir", Language::CIR) 3065a7dea167SDimitry Andric .Default(Language::Unknown); 30660b57cec5SDimitry Andric 30670b57cec5SDimitry Andric if (DashX.isUnknown()) 30680b57cec5SDimitry Andric Diags.Report(diag::err_drv_invalid_value) 30690b57cec5SDimitry Andric << A->getAsString(Args) << A->getValue(); 30700b57cec5SDimitry Andric 30710b57cec5SDimitry Andric if (Preprocessed) 30720b57cec5SDimitry Andric DashX = DashX.getPreprocessed(); 307381ad6265SDimitry Andric // A regular header is considered mutually exclusive with a header unit. 307481ad6265SDimitry Andric if (HUK != InputKind::HeaderUnit_None) { 307581ad6265SDimitry Andric DashX = DashX.withHeaderUnit(HUK); 307681ad6265SDimitry Andric IsHeaderFile = true; 307781ad6265SDimitry Andric } else if (IsHeaderFile) 307881ad6265SDimitry Andric DashX = DashX.getHeader(); 30790b57cec5SDimitry Andric if (ModuleMap) 30800b57cec5SDimitry Andric DashX = DashX.withFormat(InputKind::ModuleMap); 30810b57cec5SDimitry Andric } 30820b57cec5SDimitry Andric 30830b57cec5SDimitry Andric // '-' is the default input if none is given. 30840b57cec5SDimitry Andric std::vector<std::string> Inputs = Args.getAllArgValues(OPT_INPUT); 30850b57cec5SDimitry Andric Opts.Inputs.clear(); 30860b57cec5SDimitry Andric if (Inputs.empty()) 30870b57cec5SDimitry Andric Inputs.push_back("-"); 308881ad6265SDimitry Andric 308981ad6265SDimitry Andric if (DashX.getHeaderUnitKind() != InputKind::HeaderUnit_None && 309081ad6265SDimitry Andric Inputs.size() > 1) 309181ad6265SDimitry Andric Diags.Report(diag::err_drv_header_unit_extra_inputs) << Inputs[1]; 309281ad6265SDimitry Andric 30930b57cec5SDimitry Andric for (unsigned i = 0, e = Inputs.size(); i != e; ++i) { 30940b57cec5SDimitry Andric InputKind IK = DashX; 30950b57cec5SDimitry Andric if (IK.isUnknown()) { 30960b57cec5SDimitry Andric IK = FrontendOptions::getInputKindForExtension( 30970b57cec5SDimitry Andric StringRef(Inputs[i]).rsplit('.').second); 30980b57cec5SDimitry Andric // FIXME: Warn on this? 30990b57cec5SDimitry Andric if (IK.isUnknown()) 3100a7dea167SDimitry Andric IK = Language::C; 31010b57cec5SDimitry Andric // FIXME: Remove this hack. 31020b57cec5SDimitry Andric if (i == 0) 31030b57cec5SDimitry Andric DashX = IK; 31040b57cec5SDimitry Andric } 31050b57cec5SDimitry Andric 31065ffd83dbSDimitry Andric bool IsSystem = false; 31075ffd83dbSDimitry Andric 31080b57cec5SDimitry Andric // The -emit-module action implicitly takes a module map. 31090b57cec5SDimitry Andric if (Opts.ProgramAction == frontend::GenerateModule && 31105ffd83dbSDimitry Andric IK.getFormat() == InputKind::Source) { 31110b57cec5SDimitry Andric IK = IK.withFormat(InputKind::ModuleMap); 31125ffd83dbSDimitry Andric IsSystem = Opts.IsSystemModule; 31135ffd83dbSDimitry Andric } 31140b57cec5SDimitry Andric 31155ffd83dbSDimitry Andric Opts.Inputs.emplace_back(std::move(Inputs[i]), IK, IsSystem); 31160b57cec5SDimitry Andric } 31170b57cec5SDimitry Andric 3118fe6060f1SDimitry Andric Opts.DashX = DashX; 3119fe6060f1SDimitry Andric 3120fe6060f1SDimitry Andric return Diags.getNumErrors() == NumErrorsBefore; 31210b57cec5SDimitry Andric } 31220b57cec5SDimitry Andric 31230b57cec5SDimitry Andric std::string CompilerInvocation::GetResourcesPath(const char *Argv0, 31240b57cec5SDimitry Andric void *MainAddr) { 31250b57cec5SDimitry Andric std::string ClangExecutable = 31260b57cec5SDimitry Andric llvm::sys::fs::getMainExecutable(Argv0, MainAddr); 31270b57cec5SDimitry Andric return Driver::GetResourcesPath(ClangExecutable, CLANG_RESOURCE_DIR); 31280b57cec5SDimitry Andric } 31290b57cec5SDimitry Andric 31305f757f3fSDimitry Andric static void GenerateHeaderSearchArgs(const HeaderSearchOptions &Opts, 31315f757f3fSDimitry Andric ArgumentConsumer Consumer) { 3132fe6060f1SDimitry Andric const HeaderSearchOptions *HeaderSearchOpts = &Opts; 313306c3fb27SDimitry Andric #define HEADER_SEARCH_OPTION_WITH_MARSHALLING(...) \ 31345f757f3fSDimitry Andric GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__) 3135fe6060f1SDimitry Andric #include "clang/Driver/Options.inc" 3136fe6060f1SDimitry Andric #undef HEADER_SEARCH_OPTION_WITH_MARSHALLING 3137fe6060f1SDimitry Andric 3138fe6060f1SDimitry Andric if (Opts.UseLibcxx) 31395f757f3fSDimitry Andric GenerateArg(Consumer, OPT_stdlib_EQ, "libc++"); 3140fe6060f1SDimitry Andric 3141fe6060f1SDimitry Andric if (!Opts.ModuleCachePath.empty()) 31425f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fmodules_cache_path, Opts.ModuleCachePath); 3143fe6060f1SDimitry Andric 3144fe6060f1SDimitry Andric for (const auto &File : Opts.PrebuiltModuleFiles) 31455f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fmodule_file, File.first + "=" + File.second); 3146fe6060f1SDimitry Andric 3147fe6060f1SDimitry Andric for (const auto &Path : Opts.PrebuiltModulePaths) 31485f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fprebuilt_module_path, Path); 3149fe6060f1SDimitry Andric 3150fe6060f1SDimitry Andric for (const auto &Macro : Opts.ModulesIgnoreMacros) 31515f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fmodules_ignore_macro, Macro.val()); 3152fe6060f1SDimitry Andric 3153fe6060f1SDimitry Andric auto Matches = [](const HeaderSearchOptions::Entry &Entry, 3154fe6060f1SDimitry Andric llvm::ArrayRef<frontend::IncludeDirGroup> Groups, 3155bdd1243dSDimitry Andric std::optional<bool> IsFramework, 3156bdd1243dSDimitry Andric std::optional<bool> IgnoreSysRoot) { 3157349cc55cSDimitry Andric return llvm::is_contained(Groups, Entry.Group) && 3158fe6060f1SDimitry Andric (!IsFramework || (Entry.IsFramework == *IsFramework)) && 3159fe6060f1SDimitry Andric (!IgnoreSysRoot || (Entry.IgnoreSysRoot == *IgnoreSysRoot)); 3160fe6060f1SDimitry Andric }; 3161fe6060f1SDimitry Andric 3162fe6060f1SDimitry Andric auto It = Opts.UserEntries.begin(); 3163fe6060f1SDimitry Andric auto End = Opts.UserEntries.end(); 3164fe6060f1SDimitry Andric 3165fe6060f1SDimitry Andric // Add -I..., -F..., and -index-header-map options in order. 3166bdd1243dSDimitry Andric for (; It < End && Matches(*It, {frontend::IndexHeaderMap, frontend::Angled}, 3167bdd1243dSDimitry Andric std::nullopt, true); 3168fe6060f1SDimitry Andric ++It) { 3169fe6060f1SDimitry Andric OptSpecifier Opt = [It, Matches]() { 3170fe6060f1SDimitry Andric if (Matches(*It, frontend::IndexHeaderMap, true, true)) 3171fe6060f1SDimitry Andric return OPT_F; 3172fe6060f1SDimitry Andric if (Matches(*It, frontend::IndexHeaderMap, false, true)) 3173fe6060f1SDimitry Andric return OPT_I; 3174fe6060f1SDimitry Andric if (Matches(*It, frontend::Angled, true, true)) 3175fe6060f1SDimitry Andric return OPT_F; 3176fe6060f1SDimitry Andric if (Matches(*It, frontend::Angled, false, true)) 3177fe6060f1SDimitry Andric return OPT_I; 3178fe6060f1SDimitry Andric llvm_unreachable("Unexpected HeaderSearchOptions::Entry."); 3179fe6060f1SDimitry Andric }(); 3180fe6060f1SDimitry Andric 3181fe6060f1SDimitry Andric if (It->Group == frontend::IndexHeaderMap) 31825f757f3fSDimitry Andric GenerateArg(Consumer, OPT_index_header_map); 31835f757f3fSDimitry Andric GenerateArg(Consumer, Opt, It->Path); 3184fe6060f1SDimitry Andric }; 3185fe6060f1SDimitry Andric 3186fe6060f1SDimitry Andric // Note: some paths that came from "[-iprefix=xx] -iwithprefixbefore=yy" may 3187fe6060f1SDimitry Andric // have already been generated as "-I[xx]yy". If that's the case, their 3188fe6060f1SDimitry Andric // position on command line was such that this has no semantic impact on 3189fe6060f1SDimitry Andric // include paths. 3190fe6060f1SDimitry Andric for (; It < End && 3191fe6060f1SDimitry Andric Matches(*It, {frontend::After, frontend::Angled}, false, true); 3192fe6060f1SDimitry Andric ++It) { 3193fe6060f1SDimitry Andric OptSpecifier Opt = 3194fe6060f1SDimitry Andric It->Group == frontend::After ? OPT_iwithprefix : OPT_iwithprefixbefore; 31955f757f3fSDimitry Andric GenerateArg(Consumer, Opt, It->Path); 3196fe6060f1SDimitry Andric } 3197fe6060f1SDimitry Andric 3198fe6060f1SDimitry Andric // Note: Some paths that came from "-idirafter=xxyy" may have already been 3199fe6060f1SDimitry Andric // generated as "-iwithprefix=xxyy". If that's the case, their position on 3200fe6060f1SDimitry Andric // command line was such that this has no semantic impact on include paths. 3201fe6060f1SDimitry Andric for (; It < End && Matches(*It, {frontend::After}, false, true); ++It) 32025f757f3fSDimitry Andric GenerateArg(Consumer, OPT_idirafter, It->Path); 3203fe6060f1SDimitry Andric for (; It < End && Matches(*It, {frontend::Quoted}, false, true); ++It) 32045f757f3fSDimitry Andric GenerateArg(Consumer, OPT_iquote, It->Path); 3205bdd1243dSDimitry Andric for (; It < End && Matches(*It, {frontend::System}, false, std::nullopt); 3206bdd1243dSDimitry Andric ++It) 32075f757f3fSDimitry Andric GenerateArg(Consumer, It->IgnoreSysRoot ? OPT_isystem : OPT_iwithsysroot, 32085f757f3fSDimitry Andric It->Path); 3209fe6060f1SDimitry Andric for (; It < End && Matches(*It, {frontend::System}, true, true); ++It) 32105f757f3fSDimitry Andric GenerateArg(Consumer, OPT_iframework, It->Path); 3211fe6060f1SDimitry Andric for (; It < End && Matches(*It, {frontend::System}, true, false); ++It) 32125f757f3fSDimitry Andric GenerateArg(Consumer, OPT_iframeworkwithsysroot, It->Path); 3213fe6060f1SDimitry Andric 3214fe6060f1SDimitry Andric // Add the paths for the various language specific isystem flags. 3215fe6060f1SDimitry Andric for (; It < End && Matches(*It, {frontend::CSystem}, false, true); ++It) 32165f757f3fSDimitry Andric GenerateArg(Consumer, OPT_c_isystem, It->Path); 3217fe6060f1SDimitry Andric for (; It < End && Matches(*It, {frontend::CXXSystem}, false, true); ++It) 32185f757f3fSDimitry Andric GenerateArg(Consumer, OPT_cxx_isystem, It->Path); 3219fe6060f1SDimitry Andric for (; It < End && Matches(*It, {frontend::ObjCSystem}, false, true); ++It) 32205f757f3fSDimitry Andric GenerateArg(Consumer, OPT_objc_isystem, It->Path); 3221fe6060f1SDimitry Andric for (; It < End && Matches(*It, {frontend::ObjCXXSystem}, false, true); ++It) 32225f757f3fSDimitry Andric GenerateArg(Consumer, OPT_objcxx_isystem, It->Path); 3223fe6060f1SDimitry Andric 3224fe6060f1SDimitry Andric // Add the internal paths from a driver that detects standard include paths. 3225fe6060f1SDimitry Andric // Note: Some paths that came from "-internal-isystem" arguments may have 3226fe6060f1SDimitry Andric // already been generated as "-isystem". If that's the case, their position on 3227fe6060f1SDimitry Andric // command line was such that this has no semantic impact on include paths. 3228fe6060f1SDimitry Andric for (; It < End && 3229fe6060f1SDimitry Andric Matches(*It, {frontend::System, frontend::ExternCSystem}, false, true); 3230fe6060f1SDimitry Andric ++It) { 3231fe6060f1SDimitry Andric OptSpecifier Opt = It->Group == frontend::System 3232fe6060f1SDimitry Andric ? OPT_internal_isystem 3233fe6060f1SDimitry Andric : OPT_internal_externc_isystem; 32345f757f3fSDimitry Andric GenerateArg(Consumer, Opt, It->Path); 3235fe6060f1SDimitry Andric } 3236fe6060f1SDimitry Andric 3237fe6060f1SDimitry Andric assert(It == End && "Unhandled HeaderSearchOption::Entry."); 3238fe6060f1SDimitry Andric 3239fe6060f1SDimitry Andric // Add the path prefixes which are implicitly treated as being system headers. 3240fe6060f1SDimitry Andric for (const auto &P : Opts.SystemHeaderPrefixes) { 3241fe6060f1SDimitry Andric OptSpecifier Opt = P.IsSystemHeader ? OPT_system_header_prefix 3242fe6060f1SDimitry Andric : OPT_no_system_header_prefix; 32435f757f3fSDimitry Andric GenerateArg(Consumer, Opt, P.Prefix); 3244fe6060f1SDimitry Andric } 3245fe6060f1SDimitry Andric 3246fe6060f1SDimitry Andric for (const std::string &F : Opts.VFSOverlayFiles) 32475f757f3fSDimitry Andric GenerateArg(Consumer, OPT_ivfsoverlay, F); 3248fe6060f1SDimitry Andric } 3249fe6060f1SDimitry Andric 3250fe6060f1SDimitry Andric static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, 3251fe6060f1SDimitry Andric DiagnosticsEngine &Diags, 32520b57cec5SDimitry Andric const std::string &WorkingDir) { 3253fe6060f1SDimitry Andric unsigned NumErrorsBefore = Diags.getNumErrors(); 3254fe6060f1SDimitry Andric 3255fe6060f1SDimitry Andric HeaderSearchOptions *HeaderSearchOpts = &Opts; 3256fe6060f1SDimitry Andric 325706c3fb27SDimitry Andric #define HEADER_SEARCH_OPTION_WITH_MARSHALLING(...) \ 325806c3fb27SDimitry Andric PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__) 3259fe6060f1SDimitry Andric #include "clang/Driver/Options.inc" 3260fe6060f1SDimitry Andric #undef HEADER_SEARCH_OPTION_WITH_MARSHALLING 3261fe6060f1SDimitry Andric 32620b57cec5SDimitry Andric if (const Arg *A = Args.getLastArg(OPT_stdlib_EQ)) 32630b57cec5SDimitry Andric Opts.UseLibcxx = (strcmp(A->getValue(), "libc++") == 0); 32640b57cec5SDimitry Andric 32650b57cec5SDimitry Andric // Canonicalize -fmodules-cache-path before storing it. 32660b57cec5SDimitry Andric SmallString<128> P(Args.getLastArgValue(OPT_fmodules_cache_path)); 32670b57cec5SDimitry Andric if (!(P.empty() || llvm::sys::path::is_absolute(P))) { 32680b57cec5SDimitry Andric if (WorkingDir.empty()) 32690b57cec5SDimitry Andric llvm::sys::fs::make_absolute(P); 32700b57cec5SDimitry Andric else 32710b57cec5SDimitry Andric llvm::sys::fs::make_absolute(WorkingDir, P); 32720b57cec5SDimitry Andric } 32730b57cec5SDimitry Andric llvm::sys::path::remove_dots(P); 32747a6dacacSDimitry Andric Opts.ModuleCachePath = std::string(P); 32750b57cec5SDimitry Andric 32760b57cec5SDimitry Andric // Only the -fmodule-file=<name>=<file> form. 32770b57cec5SDimitry Andric for (const auto *A : Args.filtered(OPT_fmodule_file)) { 32780b57cec5SDimitry Andric StringRef Val = A->getValue(); 3279349cc55cSDimitry Andric if (Val.contains('=')) { 32805ffd83dbSDimitry Andric auto Split = Val.split('='); 32815f757f3fSDimitry Andric Opts.PrebuiltModuleFiles.insert_or_assign( 32825f757f3fSDimitry Andric std::string(Split.first), std::string(Split.second)); 32835ffd83dbSDimitry Andric } 32840b57cec5SDimitry Andric } 32850b57cec5SDimitry Andric for (const auto *A : Args.filtered(OPT_fprebuilt_module_path)) 32860b57cec5SDimitry Andric Opts.AddPrebuiltModulePath(A->getValue()); 32870b57cec5SDimitry Andric 32880b57cec5SDimitry Andric for (const auto *A : Args.filtered(OPT_fmodules_ignore_macro)) { 32890b57cec5SDimitry Andric StringRef MacroDef = A->getValue(); 32900b57cec5SDimitry Andric Opts.ModulesIgnoreMacros.insert( 32910b57cec5SDimitry Andric llvm::CachedHashString(MacroDef.split('=').first)); 32920b57cec5SDimitry Andric } 32930b57cec5SDimitry Andric 32940b57cec5SDimitry Andric // Add -I..., -F..., and -index-header-map options in order. 32950b57cec5SDimitry Andric bool IsIndexHeaderMap = false; 32960b57cec5SDimitry Andric bool IsSysrootSpecified = 32970b57cec5SDimitry Andric Args.hasArg(OPT__sysroot_EQ) || Args.hasArg(OPT_isysroot); 32980fca6ea1SDimitry Andric 32990fca6ea1SDimitry Andric // Expand a leading `=` to the sysroot if one was passed (and it's not a 33000fca6ea1SDimitry Andric // framework flag). 33010fca6ea1SDimitry Andric auto PrefixHeaderPath = [IsSysrootSpecified, 33020fca6ea1SDimitry Andric &Opts](const llvm::opt::Arg *A, 33030fca6ea1SDimitry Andric bool IsFramework = false) -> std::string { 33040fca6ea1SDimitry Andric assert(A->getNumValues() && "Unexpected empty search path flag!"); 33050fca6ea1SDimitry Andric if (IsSysrootSpecified && !IsFramework && A->getValue()[0] == '=') { 33060fca6ea1SDimitry Andric SmallString<32> Buffer; 33070fca6ea1SDimitry Andric llvm::sys::path::append(Buffer, Opts.Sysroot, 33080fca6ea1SDimitry Andric llvm::StringRef(A->getValue()).substr(1)); 33090fca6ea1SDimitry Andric return std::string(Buffer); 33100fca6ea1SDimitry Andric } 33110fca6ea1SDimitry Andric return A->getValue(); 33120fca6ea1SDimitry Andric }; 33130fca6ea1SDimitry Andric 33140b57cec5SDimitry Andric for (const auto *A : Args.filtered(OPT_I, OPT_F, OPT_index_header_map)) { 33150b57cec5SDimitry Andric if (A->getOption().matches(OPT_index_header_map)) { 33160b57cec5SDimitry Andric // -index-header-map applies to the next -I or -F. 33170b57cec5SDimitry Andric IsIndexHeaderMap = true; 33180b57cec5SDimitry Andric continue; 33190b57cec5SDimitry Andric } 33200b57cec5SDimitry Andric 33210b57cec5SDimitry Andric frontend::IncludeDirGroup Group = 33220b57cec5SDimitry Andric IsIndexHeaderMap ? frontend::IndexHeaderMap : frontend::Angled; 33230b57cec5SDimitry Andric 33240b57cec5SDimitry Andric bool IsFramework = A->getOption().matches(OPT_F); 33250fca6ea1SDimitry Andric Opts.AddPath(PrefixHeaderPath(A, IsFramework), Group, IsFramework, 33260b57cec5SDimitry Andric /*IgnoreSysroot*/ true); 33270b57cec5SDimitry Andric IsIndexHeaderMap = false; 33280b57cec5SDimitry Andric } 33290b57cec5SDimitry Andric 33300b57cec5SDimitry Andric // Add -iprefix/-iwithprefix/-iwithprefixbefore options. 33310b57cec5SDimitry Andric StringRef Prefix = ""; // FIXME: This isn't the correct default prefix. 33320b57cec5SDimitry Andric for (const auto *A : 33330b57cec5SDimitry Andric Args.filtered(OPT_iprefix, OPT_iwithprefix, OPT_iwithprefixbefore)) { 33340b57cec5SDimitry Andric if (A->getOption().matches(OPT_iprefix)) 33350b57cec5SDimitry Andric Prefix = A->getValue(); 33360b57cec5SDimitry Andric else if (A->getOption().matches(OPT_iwithprefix)) 33370b57cec5SDimitry Andric Opts.AddPath(Prefix.str() + A->getValue(), frontend::After, false, true); 33380b57cec5SDimitry Andric else 33390b57cec5SDimitry Andric Opts.AddPath(Prefix.str() + A->getValue(), frontend::Angled, false, true); 33400b57cec5SDimitry Andric } 33410b57cec5SDimitry Andric 33420b57cec5SDimitry Andric for (const auto *A : Args.filtered(OPT_idirafter)) 33430fca6ea1SDimitry Andric Opts.AddPath(PrefixHeaderPath(A), frontend::After, false, true); 33440b57cec5SDimitry Andric for (const auto *A : Args.filtered(OPT_iquote)) 33450fca6ea1SDimitry Andric Opts.AddPath(PrefixHeaderPath(A), frontend::Quoted, false, true); 33460fca6ea1SDimitry Andric 33470fca6ea1SDimitry Andric for (const auto *A : Args.filtered(OPT_isystem, OPT_iwithsysroot)) { 33480fca6ea1SDimitry Andric if (A->getOption().matches(OPT_iwithsysroot)) { 33490b57cec5SDimitry Andric Opts.AddPath(A->getValue(), frontend::System, false, 33500fca6ea1SDimitry Andric /*IgnoreSysRoot=*/false); 33510fca6ea1SDimitry Andric continue; 33520fca6ea1SDimitry Andric } 33530fca6ea1SDimitry Andric Opts.AddPath(PrefixHeaderPath(A), frontend::System, false, true); 33540fca6ea1SDimitry Andric } 33550b57cec5SDimitry Andric for (const auto *A : Args.filtered(OPT_iframework)) 33560b57cec5SDimitry Andric Opts.AddPath(A->getValue(), frontend::System, true, true); 33570b57cec5SDimitry Andric for (const auto *A : Args.filtered(OPT_iframeworkwithsysroot)) 33580b57cec5SDimitry Andric Opts.AddPath(A->getValue(), frontend::System, /*IsFramework=*/true, 33590b57cec5SDimitry Andric /*IgnoreSysRoot=*/false); 33600b57cec5SDimitry Andric 33610b57cec5SDimitry Andric // Add the paths for the various language specific isystem flags. 33620b57cec5SDimitry Andric for (const auto *A : Args.filtered(OPT_c_isystem)) 33630b57cec5SDimitry Andric Opts.AddPath(A->getValue(), frontend::CSystem, false, true); 33640b57cec5SDimitry Andric for (const auto *A : Args.filtered(OPT_cxx_isystem)) 33650b57cec5SDimitry Andric Opts.AddPath(A->getValue(), frontend::CXXSystem, false, true); 33660b57cec5SDimitry Andric for (const auto *A : Args.filtered(OPT_objc_isystem)) 33670b57cec5SDimitry Andric Opts.AddPath(A->getValue(), frontend::ObjCSystem, false,true); 33680b57cec5SDimitry Andric for (const auto *A : Args.filtered(OPT_objcxx_isystem)) 33690b57cec5SDimitry Andric Opts.AddPath(A->getValue(), frontend::ObjCXXSystem, false, true); 33700b57cec5SDimitry Andric 33710b57cec5SDimitry Andric // Add the internal paths from a driver that detects standard include paths. 33720b57cec5SDimitry Andric for (const auto *A : 33730b57cec5SDimitry Andric Args.filtered(OPT_internal_isystem, OPT_internal_externc_isystem)) { 33740b57cec5SDimitry Andric frontend::IncludeDirGroup Group = frontend::System; 33750b57cec5SDimitry Andric if (A->getOption().matches(OPT_internal_externc_isystem)) 33760b57cec5SDimitry Andric Group = frontend::ExternCSystem; 33770b57cec5SDimitry Andric Opts.AddPath(A->getValue(), Group, false, true); 33780b57cec5SDimitry Andric } 33790b57cec5SDimitry Andric 33800b57cec5SDimitry Andric // Add the path prefixes which are implicitly treated as being system headers. 33810b57cec5SDimitry Andric for (const auto *A : 33820b57cec5SDimitry Andric Args.filtered(OPT_system_header_prefix, OPT_no_system_header_prefix)) 33830b57cec5SDimitry Andric Opts.AddSystemHeaderPrefix( 33840b57cec5SDimitry Andric A->getValue(), A->getOption().matches(OPT_system_header_prefix)); 33850b57cec5SDimitry Andric 338606c3fb27SDimitry Andric for (const auto *A : Args.filtered(OPT_ivfsoverlay, OPT_vfsoverlay)) 33870b57cec5SDimitry Andric Opts.AddVFSOverlayFile(A->getValue()); 3388fe6060f1SDimitry Andric 3389fe6060f1SDimitry Andric return Diags.getNumErrors() == NumErrorsBefore; 33900b57cec5SDimitry Andric } 33910b57cec5SDimitry Andric 33925f757f3fSDimitry Andric static void GenerateAPINotesArgs(const APINotesOptions &Opts, 33935f757f3fSDimitry Andric ArgumentConsumer Consumer) { 33945f757f3fSDimitry Andric if (!Opts.SwiftVersion.empty()) 33955f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fapinotes_swift_version, 33965f757f3fSDimitry Andric Opts.SwiftVersion.getAsString()); 33975f757f3fSDimitry Andric 33985f757f3fSDimitry Andric for (const auto &Path : Opts.ModuleSearchPaths) 33995f757f3fSDimitry Andric GenerateArg(Consumer, OPT_iapinotes_modules, Path); 34005f757f3fSDimitry Andric } 34015f757f3fSDimitry Andric 34025f757f3fSDimitry Andric static void ParseAPINotesArgs(APINotesOptions &Opts, ArgList &Args, 34035f757f3fSDimitry Andric DiagnosticsEngine &diags) { 34045f757f3fSDimitry Andric if (const Arg *A = Args.getLastArg(OPT_fapinotes_swift_version)) { 34055f757f3fSDimitry Andric if (Opts.SwiftVersion.tryParse(A->getValue())) 34065f757f3fSDimitry Andric diags.Report(diag::err_drv_invalid_value) 34075f757f3fSDimitry Andric << A->getAsString(Args) << A->getValue(); 34085f757f3fSDimitry Andric } 34095f757f3fSDimitry Andric for (const Arg *A : Args.filtered(OPT_iapinotes_modules)) 34105f757f3fSDimitry Andric Opts.ModuleSearchPaths.push_back(A->getValue()); 34115f757f3fSDimitry Andric } 34125f757f3fSDimitry Andric 34130fca6ea1SDimitry Andric static void GeneratePointerAuthArgs(const LangOptions &Opts, 34140fca6ea1SDimitry Andric ArgumentConsumer Consumer) { 34150fca6ea1SDimitry Andric if (Opts.PointerAuthIntrinsics) 34160fca6ea1SDimitry Andric GenerateArg(Consumer, OPT_fptrauth_intrinsics); 34170fca6ea1SDimitry Andric if (Opts.PointerAuthCalls) 34180fca6ea1SDimitry Andric GenerateArg(Consumer, OPT_fptrauth_calls); 34190fca6ea1SDimitry Andric if (Opts.PointerAuthReturns) 34200fca6ea1SDimitry Andric GenerateArg(Consumer, OPT_fptrauth_returns); 34210fca6ea1SDimitry Andric if (Opts.PointerAuthIndirectGotos) 34220fca6ea1SDimitry Andric GenerateArg(Consumer, OPT_fptrauth_indirect_gotos); 34230fca6ea1SDimitry Andric if (Opts.PointerAuthAuthTraps) 34240fca6ea1SDimitry Andric GenerateArg(Consumer, OPT_fptrauth_auth_traps); 34250fca6ea1SDimitry Andric if (Opts.PointerAuthVTPtrAddressDiscrimination) 34260fca6ea1SDimitry Andric GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_address_discrimination); 34270fca6ea1SDimitry Andric if (Opts.PointerAuthVTPtrTypeDiscrimination) 34280fca6ea1SDimitry Andric GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_type_discrimination); 34290fca6ea1SDimitry Andric if (Opts.PointerAuthTypeInfoVTPtrDiscrimination) 34300fca6ea1SDimitry Andric GenerateArg(Consumer, OPT_fptrauth_type_info_vtable_pointer_discrimination); 34310fca6ea1SDimitry Andric 34320fca6ea1SDimitry Andric if (Opts.PointerAuthInitFini) 34330fca6ea1SDimitry Andric GenerateArg(Consumer, OPT_fptrauth_init_fini); 34340fca6ea1SDimitry Andric if (Opts.PointerAuthFunctionTypeDiscrimination) 34350fca6ea1SDimitry Andric GenerateArg(Consumer, OPT_fptrauth_function_pointer_type_discrimination); 34360fca6ea1SDimitry Andric } 34370fca6ea1SDimitry Andric 34380fca6ea1SDimitry Andric static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args, 34390fca6ea1SDimitry Andric DiagnosticsEngine &Diags) { 34400fca6ea1SDimitry Andric Opts.PointerAuthIntrinsics = Args.hasArg(OPT_fptrauth_intrinsics); 34410fca6ea1SDimitry Andric Opts.PointerAuthCalls = Args.hasArg(OPT_fptrauth_calls); 34420fca6ea1SDimitry Andric Opts.PointerAuthReturns = Args.hasArg(OPT_fptrauth_returns); 34430fca6ea1SDimitry Andric Opts.PointerAuthIndirectGotos = Args.hasArg(OPT_fptrauth_indirect_gotos); 34440fca6ea1SDimitry Andric Opts.PointerAuthAuthTraps = Args.hasArg(OPT_fptrauth_auth_traps); 34450fca6ea1SDimitry Andric Opts.PointerAuthVTPtrAddressDiscrimination = 34460fca6ea1SDimitry Andric Args.hasArg(OPT_fptrauth_vtable_pointer_address_discrimination); 34470fca6ea1SDimitry Andric Opts.PointerAuthVTPtrTypeDiscrimination = 34480fca6ea1SDimitry Andric Args.hasArg(OPT_fptrauth_vtable_pointer_type_discrimination); 34490fca6ea1SDimitry Andric Opts.PointerAuthTypeInfoVTPtrDiscrimination = 34500fca6ea1SDimitry Andric Args.hasArg(OPT_fptrauth_type_info_vtable_pointer_discrimination); 34510fca6ea1SDimitry Andric 34520fca6ea1SDimitry Andric Opts.PointerAuthInitFini = Args.hasArg(OPT_fptrauth_init_fini); 34530fca6ea1SDimitry Andric Opts.PointerAuthFunctionTypeDiscrimination = 34540fca6ea1SDimitry Andric Args.hasArg(OPT_fptrauth_function_pointer_type_discrimination); 34550fca6ea1SDimitry Andric } 34560fca6ea1SDimitry Andric 34570b57cec5SDimitry Andric /// Check if input file kind and language standard are compatible. 34580b57cec5SDimitry Andric static bool IsInputCompatibleWithStandard(InputKind IK, 34590b57cec5SDimitry Andric const LangStandard &S) { 34600b57cec5SDimitry Andric switch (IK.getLanguage()) { 3461a7dea167SDimitry Andric case Language::Unknown: 3462a7dea167SDimitry Andric case Language::LLVM_IR: 34630fca6ea1SDimitry Andric case Language::CIR: 34640b57cec5SDimitry Andric llvm_unreachable("should not parse language flags for this input"); 34650b57cec5SDimitry Andric 3466a7dea167SDimitry Andric case Language::C: 3467a7dea167SDimitry Andric case Language::ObjC: 3468a7dea167SDimitry Andric case Language::RenderScript: 3469a7dea167SDimitry Andric return S.getLanguage() == Language::C; 34700b57cec5SDimitry Andric 3471a7dea167SDimitry Andric case Language::OpenCL: 3472fe6060f1SDimitry Andric return S.getLanguage() == Language::OpenCL || 3473fe6060f1SDimitry Andric S.getLanguage() == Language::OpenCLCXX; 3474fe6060f1SDimitry Andric 3475fe6060f1SDimitry Andric case Language::OpenCLCXX: 3476fe6060f1SDimitry Andric return S.getLanguage() == Language::OpenCLCXX; 34770b57cec5SDimitry Andric 3478a7dea167SDimitry Andric case Language::CXX: 3479a7dea167SDimitry Andric case Language::ObjCXX: 3480a7dea167SDimitry Andric return S.getLanguage() == Language::CXX; 34810b57cec5SDimitry Andric 3482a7dea167SDimitry Andric case Language::CUDA: 34830b57cec5SDimitry Andric // FIXME: What -std= values should be permitted for CUDA compilations? 3484a7dea167SDimitry Andric return S.getLanguage() == Language::CUDA || 3485a7dea167SDimitry Andric S.getLanguage() == Language::CXX; 34860b57cec5SDimitry Andric 3487a7dea167SDimitry Andric case Language::HIP: 3488a7dea167SDimitry Andric return S.getLanguage() == Language::CXX || S.getLanguage() == Language::HIP; 34890b57cec5SDimitry Andric 3490a7dea167SDimitry Andric case Language::Asm: 34910b57cec5SDimitry Andric // Accept (and ignore) all -std= values. 34920b57cec5SDimitry Andric // FIXME: The -std= value is not ignored; it affects the tokenization 34930b57cec5SDimitry Andric // and preprocessing rules if we're preprocessing this asm input. 34940b57cec5SDimitry Andric return true; 349581ad6265SDimitry Andric 349681ad6265SDimitry Andric case Language::HLSL: 349781ad6265SDimitry Andric return S.getLanguage() == Language::HLSL; 34980b57cec5SDimitry Andric } 34990b57cec5SDimitry Andric 35000b57cec5SDimitry Andric llvm_unreachable("unexpected input language"); 35010b57cec5SDimitry Andric } 35020b57cec5SDimitry Andric 35030b57cec5SDimitry Andric /// Get language name for given input kind. 350404eeddc0SDimitry Andric static StringRef GetInputKindName(InputKind IK) { 35050b57cec5SDimitry Andric switch (IK.getLanguage()) { 3506a7dea167SDimitry Andric case Language::C: 35070b57cec5SDimitry Andric return "C"; 3508a7dea167SDimitry Andric case Language::ObjC: 35090b57cec5SDimitry Andric return "Objective-C"; 3510a7dea167SDimitry Andric case Language::CXX: 35110b57cec5SDimitry Andric return "C++"; 3512a7dea167SDimitry Andric case Language::ObjCXX: 35130b57cec5SDimitry Andric return "Objective-C++"; 3514a7dea167SDimitry Andric case Language::OpenCL: 35150b57cec5SDimitry Andric return "OpenCL"; 3516fe6060f1SDimitry Andric case Language::OpenCLCXX: 3517fe6060f1SDimitry Andric return "C++ for OpenCL"; 3518a7dea167SDimitry Andric case Language::CUDA: 35190b57cec5SDimitry Andric return "CUDA"; 3520a7dea167SDimitry Andric case Language::RenderScript: 35210b57cec5SDimitry Andric return "RenderScript"; 3522a7dea167SDimitry Andric case Language::HIP: 35230b57cec5SDimitry Andric return "HIP"; 35240b57cec5SDimitry Andric 3525a7dea167SDimitry Andric case Language::Asm: 35260b57cec5SDimitry Andric return "Asm"; 3527a7dea167SDimitry Andric case Language::LLVM_IR: 35280b57cec5SDimitry Andric return "LLVM IR"; 35290fca6ea1SDimitry Andric case Language::CIR: 35300fca6ea1SDimitry Andric return "Clang IR"; 35310b57cec5SDimitry Andric 353281ad6265SDimitry Andric case Language::HLSL: 353381ad6265SDimitry Andric return "HLSL"; 353481ad6265SDimitry Andric 3535a7dea167SDimitry Andric case Language::Unknown: 35360b57cec5SDimitry Andric break; 35370b57cec5SDimitry Andric } 35380b57cec5SDimitry Andric llvm_unreachable("unknown input language"); 35390b57cec5SDimitry Andric } 35400b57cec5SDimitry Andric 35415f757f3fSDimitry Andric void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts, 35425f757f3fSDimitry Andric ArgumentConsumer Consumer, 35435f757f3fSDimitry Andric const llvm::Triple &T, 35445f757f3fSDimitry Andric InputKind IK) { 3545fe6060f1SDimitry Andric if (IK.getFormat() == InputKind::Precompiled || 35460fca6ea1SDimitry Andric IK.getLanguage() == Language::LLVM_IR || 35470fca6ea1SDimitry Andric IK.getLanguage() == Language::CIR) { 3548fe6060f1SDimitry Andric if (Opts.ObjCAutoRefCount) 35495f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fobjc_arc); 3550fe6060f1SDimitry Andric if (Opts.PICLevel != 0) 35515f757f3fSDimitry Andric GenerateArg(Consumer, OPT_pic_level, Twine(Opts.PICLevel)); 3552fe6060f1SDimitry Andric if (Opts.PIE) 35535f757f3fSDimitry Andric GenerateArg(Consumer, OPT_pic_is_pie); 3554fe6060f1SDimitry Andric for (StringRef Sanitizer : serializeSanitizerKinds(Opts.Sanitize)) 35555f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fsanitize_EQ, Sanitizer); 3556fe6060f1SDimitry Andric 3557fe6060f1SDimitry Andric return; 3558e8d8bef9SDimitry Andric } 3559e8d8bef9SDimitry Andric 3560fe6060f1SDimitry Andric OptSpecifier StdOpt; 3561fe6060f1SDimitry Andric switch (Opts.LangStd) { 3562fe6060f1SDimitry Andric case LangStandard::lang_opencl10: 3563fe6060f1SDimitry Andric case LangStandard::lang_opencl11: 3564fe6060f1SDimitry Andric case LangStandard::lang_opencl12: 3565fe6060f1SDimitry Andric case LangStandard::lang_opencl20: 3566fe6060f1SDimitry Andric case LangStandard::lang_opencl30: 3567349cc55cSDimitry Andric case LangStandard::lang_openclcpp10: 3568349cc55cSDimitry Andric case LangStandard::lang_openclcpp2021: 3569fe6060f1SDimitry Andric StdOpt = OPT_cl_std_EQ; 3570fe6060f1SDimitry Andric break; 3571fe6060f1SDimitry Andric default: 3572fe6060f1SDimitry Andric StdOpt = OPT_std_EQ; 3573fe6060f1SDimitry Andric break; 3574fe6060f1SDimitry Andric } 3575fe6060f1SDimitry Andric 3576fe6060f1SDimitry Andric auto LangStandard = LangStandard::getLangStandardForKind(Opts.LangStd); 35775f757f3fSDimitry Andric GenerateArg(Consumer, StdOpt, LangStandard.getName()); 3578fe6060f1SDimitry Andric 3579fe6060f1SDimitry Andric if (Opts.IncludeDefaultHeader) 35805f757f3fSDimitry Andric GenerateArg(Consumer, OPT_finclude_default_header); 3581fe6060f1SDimitry Andric if (Opts.DeclareOpenCLBuiltins) 35825f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fdeclare_opencl_builtins); 3583fe6060f1SDimitry Andric 3584fe6060f1SDimitry Andric const LangOptions *LangOpts = &Opts; 3585fe6060f1SDimitry Andric 358606c3fb27SDimitry Andric #define LANG_OPTION_WITH_MARSHALLING(...) \ 35875f757f3fSDimitry Andric GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__) 3588fe6060f1SDimitry Andric #include "clang/Driver/Options.inc" 3589fe6060f1SDimitry Andric #undef LANG_OPTION_WITH_MARSHALLING 3590fe6060f1SDimitry Andric 3591fe6060f1SDimitry Andric // The '-fcf-protection=' option is generated by CodeGenOpts generator. 3592fe6060f1SDimitry Andric 3593fe6060f1SDimitry Andric if (Opts.ObjC) { 35945f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fobjc_runtime_EQ, Opts.ObjCRuntime.getAsString()); 3595fe6060f1SDimitry Andric 3596fe6060f1SDimitry Andric if (Opts.GC == LangOptions::GCOnly) 35975f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fobjc_gc_only); 3598fe6060f1SDimitry Andric else if (Opts.GC == LangOptions::HybridGC) 35995f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fobjc_gc); 3600fe6060f1SDimitry Andric else if (Opts.ObjCAutoRefCount == 1) 36015f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fobjc_arc); 3602fe6060f1SDimitry Andric 3603fe6060f1SDimitry Andric if (Opts.ObjCWeakRuntime) 36045f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fobjc_runtime_has_weak); 3605fe6060f1SDimitry Andric 3606fe6060f1SDimitry Andric if (Opts.ObjCWeak) 36075f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fobjc_weak); 3608fe6060f1SDimitry Andric 3609fe6060f1SDimitry Andric if (Opts.ObjCSubscriptingLegacyRuntime) 36105f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fobjc_subscripting_legacy_runtime); 3611fe6060f1SDimitry Andric } 3612fe6060f1SDimitry Andric 3613fe6060f1SDimitry Andric if (Opts.GNUCVersion != 0) { 3614fe6060f1SDimitry Andric unsigned Major = Opts.GNUCVersion / 100 / 100; 3615fe6060f1SDimitry Andric unsigned Minor = (Opts.GNUCVersion / 100) % 100; 3616fe6060f1SDimitry Andric unsigned Patch = Opts.GNUCVersion % 100; 36175f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fgnuc_version_EQ, 36185f757f3fSDimitry Andric Twine(Major) + "." + Twine(Minor) + "." + Twine(Patch)); 3619fe6060f1SDimitry Andric } 3620fe6060f1SDimitry Andric 3621fe6060f1SDimitry Andric if (Opts.IgnoreXCOFFVisibility) 36225f757f3fSDimitry Andric GenerateArg(Consumer, OPT_mignore_xcoff_visibility); 3623fe6060f1SDimitry Andric 3624fe6060f1SDimitry Andric if (Opts.SignedOverflowBehavior == LangOptions::SOB_Trapping) { 36255f757f3fSDimitry Andric GenerateArg(Consumer, OPT_ftrapv); 36265f757f3fSDimitry Andric GenerateArg(Consumer, OPT_ftrapv_handler, Opts.OverflowHandler); 3627fe6060f1SDimitry Andric } else if (Opts.SignedOverflowBehavior == LangOptions::SOB_Defined) { 36285f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fwrapv); 3629fe6060f1SDimitry Andric } 3630fe6060f1SDimitry Andric 3631fe6060f1SDimitry Andric if (Opts.MSCompatibilityVersion != 0) { 3632fe6060f1SDimitry Andric unsigned Major = Opts.MSCompatibilityVersion / 10000000; 3633fe6060f1SDimitry Andric unsigned Minor = (Opts.MSCompatibilityVersion / 100000) % 100; 3634fe6060f1SDimitry Andric unsigned Subminor = Opts.MSCompatibilityVersion % 100000; 36355f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fms_compatibility_version, 36365f757f3fSDimitry Andric Twine(Major) + "." + Twine(Minor) + "." + Twine(Subminor)); 3637fe6060f1SDimitry Andric } 3638fe6060f1SDimitry Andric 36397a6dacacSDimitry Andric if ((!Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus17 && !Opts.C23) || 36407a6dacacSDimitry Andric T.isOSzOS()) { 3641fe6060f1SDimitry Andric if (!Opts.Trigraphs) 36425f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fno_trigraphs); 3643fe6060f1SDimitry Andric } else { 3644fe6060f1SDimitry Andric if (Opts.Trigraphs) 36455f757f3fSDimitry Andric GenerateArg(Consumer, OPT_ftrigraphs); 3646fe6060f1SDimitry Andric } 3647fe6060f1SDimitry Andric 3648fe6060f1SDimitry Andric if (Opts.Blocks && !(Opts.OpenCL && Opts.OpenCLVersion == 200)) 36495f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fblocks); 3650fe6060f1SDimitry Andric 3651fe6060f1SDimitry Andric if (Opts.ConvergentFunctions && 36520fca6ea1SDimitry Andric !(Opts.OpenCL || (Opts.CUDA && Opts.CUDAIsDevice) || Opts.SYCLIsDevice || 36530fca6ea1SDimitry Andric Opts.HLSL)) 36545f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fconvergent_functions); 3655fe6060f1SDimitry Andric 3656fe6060f1SDimitry Andric if (Opts.NoBuiltin && !Opts.Freestanding) 36575f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fno_builtin); 3658fe6060f1SDimitry Andric 3659fe6060f1SDimitry Andric if (!Opts.NoBuiltin) 3660fe6060f1SDimitry Andric for (const auto &Func : Opts.NoBuiltinFuncs) 36615f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fno_builtin_, Func); 3662fe6060f1SDimitry Andric 3663fe6060f1SDimitry Andric if (Opts.LongDoubleSize == 128) 36645f757f3fSDimitry Andric GenerateArg(Consumer, OPT_mlong_double_128); 3665fe6060f1SDimitry Andric else if (Opts.LongDoubleSize == 64) 36665f757f3fSDimitry Andric GenerateArg(Consumer, OPT_mlong_double_64); 366781ad6265SDimitry Andric else if (Opts.LongDoubleSize == 80) 36685f757f3fSDimitry Andric GenerateArg(Consumer, OPT_mlong_double_80); 3669fe6060f1SDimitry Andric 3670fe6060f1SDimitry Andric // Not generating '-mrtd', it's just an alias for '-fdefault-calling-conv='. 3671fe6060f1SDimitry Andric 3672fe6060f1SDimitry Andric // OpenMP was requested via '-fopenmp', not implied by '-fopenmp-simd' or 3673fe6060f1SDimitry Andric // '-fopenmp-targets='. 3674fe6060f1SDimitry Andric if (Opts.OpenMP && !Opts.OpenMPSimd) { 36755f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fopenmp); 3676fe6060f1SDimitry Andric 367706c3fb27SDimitry Andric if (Opts.OpenMP != 51) 36785f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fopenmp_version_EQ, Twine(Opts.OpenMP)); 3679fe6060f1SDimitry Andric 3680fe6060f1SDimitry Andric if (!Opts.OpenMPUseTLS) 36815f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fnoopenmp_use_tls); 3682fe6060f1SDimitry Andric 368306c3fb27SDimitry Andric if (Opts.OpenMPIsTargetDevice) 36845f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fopenmp_is_target_device); 3685fe6060f1SDimitry Andric 3686fe6060f1SDimitry Andric if (Opts.OpenMPIRBuilder) 36875f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fopenmp_enable_irbuilder); 3688fe6060f1SDimitry Andric } 3689fe6060f1SDimitry Andric 3690fe6060f1SDimitry Andric if (Opts.OpenMPSimd) { 36915f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fopenmp_simd); 3692fe6060f1SDimitry Andric 369306c3fb27SDimitry Andric if (Opts.OpenMP != 51) 36945f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fopenmp_version_EQ, Twine(Opts.OpenMP)); 3695fe6060f1SDimitry Andric } 3696fe6060f1SDimitry Andric 3697349cc55cSDimitry Andric if (Opts.OpenMPThreadSubscription) 36985f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fopenmp_assume_threads_oversubscription); 3699349cc55cSDimitry Andric 3700349cc55cSDimitry Andric if (Opts.OpenMPTeamSubscription) 37015f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fopenmp_assume_teams_oversubscription); 3702349cc55cSDimitry Andric 3703349cc55cSDimitry Andric if (Opts.OpenMPTargetDebug != 0) 37045f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fopenmp_target_debug_EQ, 37055f757f3fSDimitry Andric Twine(Opts.OpenMPTargetDebug)); 3706349cc55cSDimitry Andric 3707fe6060f1SDimitry Andric if (Opts.OpenMPCUDANumSMs != 0) 37085f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fopenmp_cuda_number_of_sm_EQ, 37095f757f3fSDimitry Andric Twine(Opts.OpenMPCUDANumSMs)); 3710fe6060f1SDimitry Andric 3711fe6060f1SDimitry Andric if (Opts.OpenMPCUDABlocksPerSM != 0) 37125f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fopenmp_cuda_blocks_per_sm_EQ, 37135f757f3fSDimitry Andric Twine(Opts.OpenMPCUDABlocksPerSM)); 3714fe6060f1SDimitry Andric 3715fe6060f1SDimitry Andric if (Opts.OpenMPCUDAReductionBufNum != 1024) 37165f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fopenmp_cuda_teams_reduction_recs_num_EQ, 37175f757f3fSDimitry Andric Twine(Opts.OpenMPCUDAReductionBufNum)); 3718fe6060f1SDimitry Andric 3719fe6060f1SDimitry Andric if (!Opts.OMPTargetTriples.empty()) { 3720fe6060f1SDimitry Andric std::string Targets; 3721fe6060f1SDimitry Andric llvm::raw_string_ostream OS(Targets); 3722fe6060f1SDimitry Andric llvm::interleave( 3723fe6060f1SDimitry Andric Opts.OMPTargetTriples, OS, 3724fe6060f1SDimitry Andric [&OS](const llvm::Triple &T) { OS << T.str(); }, ","); 37255f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fopenmp_targets_EQ, OS.str()); 3726fe6060f1SDimitry Andric } 3727fe6060f1SDimitry Andric 3728fe6060f1SDimitry Andric if (!Opts.OMPHostIRFile.empty()) 37295f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fopenmp_host_ir_file_path, Opts.OMPHostIRFile); 3730fe6060f1SDimitry Andric 3731fe6060f1SDimitry Andric if (Opts.OpenMPCUDAMode) 37325f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fopenmp_cuda_mode); 37335f757f3fSDimitry Andric 37345f757f3fSDimitry Andric if (Opts.OpenACC) { 37355f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fopenacc); 37365f757f3fSDimitry Andric if (!Opts.OpenACCMacroOverride.empty()) 37375f757f3fSDimitry Andric GenerateArg(Consumer, OPT_openacc_macro_override, 37385f757f3fSDimitry Andric Opts.OpenACCMacroOverride); 37395f757f3fSDimitry Andric } 3740fe6060f1SDimitry Andric 3741fe6060f1SDimitry Andric // The arguments used to set Optimize, OptimizeSize and NoInlineDefine are 3742fe6060f1SDimitry Andric // generated from CodeGenOptions. 3743fe6060f1SDimitry Andric 3744fe6060f1SDimitry Andric if (Opts.DefaultFPContractMode == LangOptions::FPM_Fast) 37455f757f3fSDimitry Andric GenerateArg(Consumer, OPT_ffp_contract, "fast"); 3746fe6060f1SDimitry Andric else if (Opts.DefaultFPContractMode == LangOptions::FPM_On) 37475f757f3fSDimitry Andric GenerateArg(Consumer, OPT_ffp_contract, "on"); 3748fe6060f1SDimitry Andric else if (Opts.DefaultFPContractMode == LangOptions::FPM_Off) 37495f757f3fSDimitry Andric GenerateArg(Consumer, OPT_ffp_contract, "off"); 3750fe6060f1SDimitry Andric else if (Opts.DefaultFPContractMode == LangOptions::FPM_FastHonorPragmas) 37515f757f3fSDimitry Andric GenerateArg(Consumer, OPT_ffp_contract, "fast-honor-pragmas"); 3752fe6060f1SDimitry Andric 3753fe6060f1SDimitry Andric for (StringRef Sanitizer : serializeSanitizerKinds(Opts.Sanitize)) 37545f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fsanitize_EQ, Sanitizer); 3755fe6060f1SDimitry Andric 3756fe6060f1SDimitry Andric // Conflating '-fsanitize-system-ignorelist' and '-fsanitize-ignorelist'. 3757fe6060f1SDimitry Andric for (const std::string &F : Opts.NoSanitizeFiles) 37585f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fsanitize_ignorelist_EQ, F); 3759fe6060f1SDimitry Andric 37605f757f3fSDimitry Andric switch (Opts.getClangABICompat()) { 37615f757f3fSDimitry Andric case LangOptions::ClangABI::Ver3_8: 37625f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "3.8"); 37635f757f3fSDimitry Andric break; 37645f757f3fSDimitry Andric case LangOptions::ClangABI::Ver4: 37655f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "4.0"); 37665f757f3fSDimitry Andric break; 37675f757f3fSDimitry Andric case LangOptions::ClangABI::Ver6: 37685f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "6.0"); 37695f757f3fSDimitry Andric break; 37705f757f3fSDimitry Andric case LangOptions::ClangABI::Ver7: 37715f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "7.0"); 37725f757f3fSDimitry Andric break; 37735f757f3fSDimitry Andric case LangOptions::ClangABI::Ver9: 37745f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "9.0"); 37755f757f3fSDimitry Andric break; 37765f757f3fSDimitry Andric case LangOptions::ClangABI::Ver11: 37775f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "11.0"); 37785f757f3fSDimitry Andric break; 37795f757f3fSDimitry Andric case LangOptions::ClangABI::Ver12: 37805f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "12.0"); 37815f757f3fSDimitry Andric break; 37825f757f3fSDimitry Andric case LangOptions::ClangABI::Ver14: 37835f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "14.0"); 37845f757f3fSDimitry Andric break; 37855f757f3fSDimitry Andric case LangOptions::ClangABI::Ver15: 37865f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "15.0"); 37875f757f3fSDimitry Andric break; 37885f757f3fSDimitry Andric case LangOptions::ClangABI::Ver17: 37895f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "17.0"); 37905f757f3fSDimitry Andric break; 37910fca6ea1SDimitry Andric case LangOptions::ClangABI::Ver18: 37920fca6ea1SDimitry Andric GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "18.0"); 37930fca6ea1SDimitry Andric break; 37945f757f3fSDimitry Andric case LangOptions::ClangABI::Latest: 37955f757f3fSDimitry Andric break; 37965f757f3fSDimitry Andric } 3797fe6060f1SDimitry Andric 3798fe6060f1SDimitry Andric if (Opts.getSignReturnAddressScope() == 3799fe6060f1SDimitry Andric LangOptions::SignReturnAddressScopeKind::All) 38005f757f3fSDimitry Andric GenerateArg(Consumer, OPT_msign_return_address_EQ, "all"); 3801fe6060f1SDimitry Andric else if (Opts.getSignReturnAddressScope() == 3802fe6060f1SDimitry Andric LangOptions::SignReturnAddressScopeKind::NonLeaf) 38035f757f3fSDimitry Andric GenerateArg(Consumer, OPT_msign_return_address_EQ, "non-leaf"); 3804fe6060f1SDimitry Andric 3805fe6060f1SDimitry Andric if (Opts.getSignReturnAddressKey() == 3806fe6060f1SDimitry Andric LangOptions::SignReturnAddressKeyKind::BKey) 38075f757f3fSDimitry Andric GenerateArg(Consumer, OPT_msign_return_address_key_EQ, "b_key"); 3808fe6060f1SDimitry Andric 3809fe6060f1SDimitry Andric if (Opts.CXXABI) 38105f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fcxx_abi_EQ, 38115f757f3fSDimitry Andric TargetCXXABI::getSpelling(*Opts.CXXABI)); 3812fe6060f1SDimitry Andric 3813fe6060f1SDimitry Andric if (Opts.RelativeCXXABIVTables) 38145f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fexperimental_relative_cxx_abi_vtables); 3815fe6060f1SDimitry Andric else 38165f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fno_experimental_relative_cxx_abi_vtables); 38176e75b2fbSDimitry Andric 381881ad6265SDimitry Andric if (Opts.UseTargetPathSeparator) 38195f757f3fSDimitry Andric GenerateArg(Consumer, OPT_ffile_reproducible); 382081ad6265SDimitry Andric else 38215f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fno_file_reproducible); 382281ad6265SDimitry Andric 38236e75b2fbSDimitry Andric for (const auto &MP : Opts.MacroPrefixMap) 38245f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fmacro_prefix_map_EQ, MP.first + "=" + MP.second); 382581ad6265SDimitry Andric 382681ad6265SDimitry Andric if (!Opts.RandstructSeed.empty()) 38275f757f3fSDimitry Andric GenerateArg(Consumer, OPT_frandomize_layout_seed_EQ, Opts.RandstructSeed); 3828fe6060f1SDimitry Andric } 3829fe6060f1SDimitry Andric 3830fe6060f1SDimitry Andric bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, 3831e8d8bef9SDimitry Andric InputKind IK, const llvm::Triple &T, 3832e8d8bef9SDimitry Andric std::vector<std::string> &Includes, 38330b57cec5SDimitry Andric DiagnosticsEngine &Diags) { 3834fe6060f1SDimitry Andric unsigned NumErrorsBefore = Diags.getNumErrors(); 3835fe6060f1SDimitry Andric 3836fe6060f1SDimitry Andric if (IK.getFormat() == InputKind::Precompiled || 38370fca6ea1SDimitry Andric IK.getLanguage() == Language::LLVM_IR || 38380fca6ea1SDimitry Andric IK.getLanguage() == Language::CIR) { 3839fe6060f1SDimitry Andric // ObjCAAutoRefCount and Sanitize LangOpts are used to setup the 3840fe6060f1SDimitry Andric // PassManager in BackendUtil.cpp. They need to be initialized no matter 3841fe6060f1SDimitry Andric // what the input type is. 3842fe6060f1SDimitry Andric if (Args.hasArg(OPT_fobjc_arc)) 3843fe6060f1SDimitry Andric Opts.ObjCAutoRefCount = 1; 3844fe6060f1SDimitry Andric // PICLevel and PIELevel are needed during code generation and this should 3845fe6060f1SDimitry Andric // be set regardless of the input type. 3846fe6060f1SDimitry Andric Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags); 3847fe6060f1SDimitry Andric Opts.PIE = Args.hasArg(OPT_pic_is_pie); 3848fe6060f1SDimitry Andric parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ), 3849fe6060f1SDimitry Andric Diags, Opts.Sanitize); 3850fe6060f1SDimitry Andric 3851fe6060f1SDimitry Andric return Diags.getNumErrors() == NumErrorsBefore; 3852fe6060f1SDimitry Andric } 3853fe6060f1SDimitry Andric 3854fe6060f1SDimitry Andric // Other LangOpts are only initialized when the input is not AST or LLVM IR. 3855fe6060f1SDimitry Andric // FIXME: Should we really be parsing this for an Language::Asm input? 3856fe6060f1SDimitry Andric 38570b57cec5SDimitry Andric // FIXME: Cleanup per-file based stuff. 38580b57cec5SDimitry Andric LangStandard::Kind LangStd = LangStandard::lang_unspecified; 38590b57cec5SDimitry Andric if (const Arg *A = Args.getLastArg(OPT_std_EQ)) { 3860a7dea167SDimitry Andric LangStd = LangStandard::getLangKind(A->getValue()); 38610b57cec5SDimitry Andric if (LangStd == LangStandard::lang_unspecified) { 38620b57cec5SDimitry Andric Diags.Report(diag::err_drv_invalid_value) 38630b57cec5SDimitry Andric << A->getAsString(Args) << A->getValue(); 38640b57cec5SDimitry Andric // Report supported standards with short description. 38650b57cec5SDimitry Andric for (unsigned KindValue = 0; 38660b57cec5SDimitry Andric KindValue != LangStandard::lang_unspecified; 38670b57cec5SDimitry Andric ++KindValue) { 38680b57cec5SDimitry Andric const LangStandard &Std = LangStandard::getLangStandardForKind( 38690b57cec5SDimitry Andric static_cast<LangStandard::Kind>(KindValue)); 38700b57cec5SDimitry Andric if (IsInputCompatibleWithStandard(IK, Std)) { 38710b57cec5SDimitry Andric auto Diag = Diags.Report(diag::note_drv_use_standard); 38720b57cec5SDimitry Andric Diag << Std.getName() << Std.getDescription(); 38730b57cec5SDimitry Andric unsigned NumAliases = 0; 38740b57cec5SDimitry Andric #define LANGSTANDARD(id, name, lang, desc, features) 38750b57cec5SDimitry Andric #define LANGSTANDARD_ALIAS(id, alias) \ 38760b57cec5SDimitry Andric if (KindValue == LangStandard::lang_##id) ++NumAliases; 38770b57cec5SDimitry Andric #define LANGSTANDARD_ALIAS_DEPR(id, alias) 3878a7dea167SDimitry Andric #include "clang/Basic/LangStandards.def" 38790b57cec5SDimitry Andric Diag << NumAliases; 38800b57cec5SDimitry Andric #define LANGSTANDARD(id, name, lang, desc, features) 38810b57cec5SDimitry Andric #define LANGSTANDARD_ALIAS(id, alias) \ 38820b57cec5SDimitry Andric if (KindValue == LangStandard::lang_##id) Diag << alias; 38830b57cec5SDimitry Andric #define LANGSTANDARD_ALIAS_DEPR(id, alias) 3884a7dea167SDimitry Andric #include "clang/Basic/LangStandards.def" 38850b57cec5SDimitry Andric } 38860b57cec5SDimitry Andric } 38870b57cec5SDimitry Andric } else { 38880b57cec5SDimitry Andric // Valid standard, check to make sure language and standard are 38890b57cec5SDimitry Andric // compatible. 38900b57cec5SDimitry Andric const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd); 38910b57cec5SDimitry Andric if (!IsInputCompatibleWithStandard(IK, Std)) { 38920b57cec5SDimitry Andric Diags.Report(diag::err_drv_argument_not_allowed_with) 38930b57cec5SDimitry Andric << A->getAsString(Args) << GetInputKindName(IK); 38940b57cec5SDimitry Andric } 38950b57cec5SDimitry Andric } 38960b57cec5SDimitry Andric } 38970b57cec5SDimitry Andric 38980b57cec5SDimitry Andric // -cl-std only applies for OpenCL language standards. 38990b57cec5SDimitry Andric // Override the -std option in this case. 39000b57cec5SDimitry Andric if (const Arg *A = Args.getLastArg(OPT_cl_std_EQ)) { 39010b57cec5SDimitry Andric LangStandard::Kind OpenCLLangStd 39020b57cec5SDimitry Andric = llvm::StringSwitch<LangStandard::Kind>(A->getValue()) 39030b57cec5SDimitry Andric .Cases("cl", "CL", LangStandard::lang_opencl10) 3904e8d8bef9SDimitry Andric .Cases("cl1.0", "CL1.0", LangStandard::lang_opencl10) 39050b57cec5SDimitry Andric .Cases("cl1.1", "CL1.1", LangStandard::lang_opencl11) 39060b57cec5SDimitry Andric .Cases("cl1.2", "CL1.2", LangStandard::lang_opencl12) 39070b57cec5SDimitry Andric .Cases("cl2.0", "CL2.0", LangStandard::lang_opencl20) 3908e8d8bef9SDimitry Andric .Cases("cl3.0", "CL3.0", LangStandard::lang_opencl30) 3909349cc55cSDimitry Andric .Cases("clc++", "CLC++", LangStandard::lang_openclcpp10) 3910349cc55cSDimitry Andric .Cases("clc++1.0", "CLC++1.0", LangStandard::lang_openclcpp10) 3911349cc55cSDimitry Andric .Cases("clc++2021", "CLC++2021", LangStandard::lang_openclcpp2021) 39120b57cec5SDimitry Andric .Default(LangStandard::lang_unspecified); 39130b57cec5SDimitry Andric 39140b57cec5SDimitry Andric if (OpenCLLangStd == LangStandard::lang_unspecified) { 39150b57cec5SDimitry Andric Diags.Report(diag::err_drv_invalid_value) 39160b57cec5SDimitry Andric << A->getAsString(Args) << A->getValue(); 39170b57cec5SDimitry Andric } 39180b57cec5SDimitry Andric else 39190b57cec5SDimitry Andric LangStd = OpenCLLangStd; 39200b57cec5SDimitry Andric } 39210b57cec5SDimitry Andric 3922e8d8bef9SDimitry Andric // These need to be parsed now. They are used to set OpenCL defaults. 39230b57cec5SDimitry Andric Opts.IncludeDefaultHeader = Args.hasArg(OPT_finclude_default_header); 39240b57cec5SDimitry Andric Opts.DeclareOpenCLBuiltins = Args.hasArg(OPT_fdeclare_opencl_builtins); 39250b57cec5SDimitry Andric 392681ad6265SDimitry Andric LangOptions::setLangDefaults(Opts, IK.getLanguage(), T, Includes, LangStd); 39270b57cec5SDimitry Andric 3928e8d8bef9SDimitry Andric // The key paths of codegen options defined in Options.td start with 3929e8d8bef9SDimitry Andric // "LangOpts->". Let's provide the expected variable name and type. 3930e8d8bef9SDimitry Andric LangOptions *LangOpts = &Opts; 3931e8d8bef9SDimitry Andric 393206c3fb27SDimitry Andric #define LANG_OPTION_WITH_MARSHALLING(...) \ 393306c3fb27SDimitry Andric PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__) 3934e8d8bef9SDimitry Andric #include "clang/Driver/Options.inc" 3935e8d8bef9SDimitry Andric #undef LANG_OPTION_WITH_MARSHALLING 3936e8d8bef9SDimitry Andric 3937e8d8bef9SDimitry Andric if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) { 3938e8d8bef9SDimitry Andric StringRef Name = A->getValue(); 3939e8d8bef9SDimitry Andric if (Name == "full" || Name == "branch") { 3940e8d8bef9SDimitry Andric Opts.CFProtectionBranch = 1; 39410b57cec5SDimitry Andric } 3942e8d8bef9SDimitry Andric } 39430b57cec5SDimitry Andric 3944fe6060f1SDimitry Andric if ((Args.hasArg(OPT_fsycl_is_device) || Args.hasArg(OPT_fsycl_is_host)) && 3945fe6060f1SDimitry Andric !Args.hasArg(OPT_sycl_std_EQ)) { 3946fe6060f1SDimitry Andric // If the user supplied -fsycl-is-device or -fsycl-is-host, but failed to 3947fe6060f1SDimitry Andric // provide -sycl-std=, we want to default it to whatever the default SYCL 3948fe6060f1SDimitry Andric // version is. I could not find a way to express this with the options 3949fe6060f1SDimitry Andric // tablegen because we still want this value to be SYCL_None when the user 3950fe6060f1SDimitry Andric // is not in device or host mode. 3951fe6060f1SDimitry Andric Opts.setSYCLVersion(LangOptions::SYCL_Default); 3952fe6060f1SDimitry Andric } 39530b57cec5SDimitry Andric 39540b57cec5SDimitry Andric if (Opts.ObjC) { 39550b57cec5SDimitry Andric if (Arg *arg = Args.getLastArg(OPT_fobjc_runtime_EQ)) { 39560b57cec5SDimitry Andric StringRef value = arg->getValue(); 39570b57cec5SDimitry Andric if (Opts.ObjCRuntime.tryParse(value)) 39580b57cec5SDimitry Andric Diags.Report(diag::err_drv_unknown_objc_runtime) << value; 39590b57cec5SDimitry Andric } 39600b57cec5SDimitry Andric 39610b57cec5SDimitry Andric if (Args.hasArg(OPT_fobjc_gc_only)) 39620b57cec5SDimitry Andric Opts.setGC(LangOptions::GCOnly); 39630b57cec5SDimitry Andric else if (Args.hasArg(OPT_fobjc_gc)) 39640b57cec5SDimitry Andric Opts.setGC(LangOptions::HybridGC); 39650b57cec5SDimitry Andric else if (Args.hasArg(OPT_fobjc_arc)) { 39660b57cec5SDimitry Andric Opts.ObjCAutoRefCount = 1; 39670b57cec5SDimitry Andric if (!Opts.ObjCRuntime.allowsARC()) 39680b57cec5SDimitry Andric Diags.Report(diag::err_arc_unsupported_on_runtime); 39690b57cec5SDimitry Andric } 39700b57cec5SDimitry Andric 39710b57cec5SDimitry Andric // ObjCWeakRuntime tracks whether the runtime supports __weak, not 39720b57cec5SDimitry Andric // whether the feature is actually enabled. This is predominantly 39730b57cec5SDimitry Andric // determined by -fobjc-runtime, but we allow it to be overridden 39740b57cec5SDimitry Andric // from the command line for testing purposes. 39750b57cec5SDimitry Andric if (Args.hasArg(OPT_fobjc_runtime_has_weak)) 39760b57cec5SDimitry Andric Opts.ObjCWeakRuntime = 1; 39770b57cec5SDimitry Andric else 39780b57cec5SDimitry Andric Opts.ObjCWeakRuntime = Opts.ObjCRuntime.allowsWeak(); 39790b57cec5SDimitry Andric 39800b57cec5SDimitry Andric // ObjCWeak determines whether __weak is actually enabled. 39810b57cec5SDimitry Andric // Note that we allow -fno-objc-weak to disable this even in ARC mode. 39820b57cec5SDimitry Andric if (auto weakArg = Args.getLastArg(OPT_fobjc_weak, OPT_fno_objc_weak)) { 39830b57cec5SDimitry Andric if (!weakArg->getOption().matches(OPT_fobjc_weak)) { 39840b57cec5SDimitry Andric assert(!Opts.ObjCWeak); 39850b57cec5SDimitry Andric } else if (Opts.getGC() != LangOptions::NonGC) { 39860b57cec5SDimitry Andric Diags.Report(diag::err_objc_weak_with_gc); 39870b57cec5SDimitry Andric } else if (!Opts.ObjCWeakRuntime) { 39880b57cec5SDimitry Andric Diags.Report(diag::err_objc_weak_unsupported); 39890b57cec5SDimitry Andric } else { 39900b57cec5SDimitry Andric Opts.ObjCWeak = 1; 39910b57cec5SDimitry Andric } 39920b57cec5SDimitry Andric } else if (Opts.ObjCAutoRefCount) { 39930b57cec5SDimitry Andric Opts.ObjCWeak = Opts.ObjCWeakRuntime; 39940b57cec5SDimitry Andric } 39950b57cec5SDimitry Andric 39960b57cec5SDimitry Andric if (Args.hasArg(OPT_fobjc_subscripting_legacy_runtime)) 39970b57cec5SDimitry Andric Opts.ObjCSubscriptingLegacyRuntime = 39980b57cec5SDimitry Andric (Opts.ObjCRuntime.getKind() == ObjCRuntime::FragileMacOSX); 39990b57cec5SDimitry Andric } 40000b57cec5SDimitry Andric 4001a7dea167SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_fgnuc_version_EQ)) { 4002a7dea167SDimitry Andric // Check that the version has 1 to 3 components and the minor and patch 4003a7dea167SDimitry Andric // versions fit in two decimal digits. 4004a7dea167SDimitry Andric VersionTuple GNUCVer; 4005a7dea167SDimitry Andric bool Invalid = GNUCVer.tryParse(A->getValue()); 4006a7dea167SDimitry Andric unsigned Major = GNUCVer.getMajor(); 400781ad6265SDimitry Andric unsigned Minor = GNUCVer.getMinor().value_or(0); 400881ad6265SDimitry Andric unsigned Patch = GNUCVer.getSubminor().value_or(0); 4009a7dea167SDimitry Andric if (Invalid || GNUCVer.getBuild() || Minor >= 100 || Patch >= 100) { 4010a7dea167SDimitry Andric Diags.Report(diag::err_drv_invalid_value) 4011a7dea167SDimitry Andric << A->getAsString(Args) << A->getValue(); 4012a7dea167SDimitry Andric } 4013a7dea167SDimitry Andric Opts.GNUCVersion = Major * 100 * 100 + Minor * 100 + Patch; 4014a7dea167SDimitry Andric } 4015a7dea167SDimitry Andric 401681ad6265SDimitry Andric if (T.isOSAIX() && (Args.hasArg(OPT_mignore_xcoff_visibility))) 4017fe6060f1SDimitry Andric Opts.IgnoreXCOFFVisibility = 1; 4018fe6060f1SDimitry Andric 40190b57cec5SDimitry Andric if (Args.hasArg(OPT_ftrapv)) { 40200b57cec5SDimitry Andric Opts.setSignedOverflowBehavior(LangOptions::SOB_Trapping); 40210b57cec5SDimitry Andric // Set the handler, if one is specified. 40220b57cec5SDimitry Andric Opts.OverflowHandler = 40235ffd83dbSDimitry Andric std::string(Args.getLastArgValue(OPT_ftrapv_handler)); 40240b57cec5SDimitry Andric } 40250b57cec5SDimitry Andric else if (Args.hasArg(OPT_fwrapv)) 40260b57cec5SDimitry Andric Opts.setSignedOverflowBehavior(LangOptions::SOB_Defined); 40270b57cec5SDimitry Andric 40280b57cec5SDimitry Andric Opts.MSCompatibilityVersion = 0; 40290b57cec5SDimitry Andric if (const Arg *A = Args.getLastArg(OPT_fms_compatibility_version)) { 40300b57cec5SDimitry Andric VersionTuple VT; 40310b57cec5SDimitry Andric if (VT.tryParse(A->getValue())) 40320b57cec5SDimitry Andric Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) 40330b57cec5SDimitry Andric << A->getValue(); 40340b57cec5SDimitry Andric Opts.MSCompatibilityVersion = VT.getMajor() * 10000000 + 403581ad6265SDimitry Andric VT.getMinor().value_or(0) * 100000 + 403681ad6265SDimitry Andric VT.getSubminor().value_or(0); 40370b57cec5SDimitry Andric } 40380b57cec5SDimitry Andric 40390b57cec5SDimitry Andric // Mimicking gcc's behavior, trigraphs are only enabled if -trigraphs 40400b57cec5SDimitry Andric // is specified, or -std is set to a conforming mode. 40417a6dacacSDimitry Andric // Trigraphs are disabled by default in C++17 and C23 onwards. 4042e8d8bef9SDimitry Andric // For z/OS, trigraphs are enabled by default (without regard to the above). 4043e8d8bef9SDimitry Andric Opts.Trigraphs = 40447a6dacacSDimitry Andric (!Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus17 && !Opts.C23) || 40457a6dacacSDimitry Andric T.isOSzOS(); 40460b57cec5SDimitry Andric Opts.Trigraphs = 40470b57cec5SDimitry Andric Args.hasFlag(OPT_ftrigraphs, OPT_fno_trigraphs, Opts.Trigraphs); 40480b57cec5SDimitry Andric 40490b57cec5SDimitry Andric Opts.Blocks = Args.hasArg(OPT_fblocks) || (Opts.OpenCL 40500b57cec5SDimitry Andric && Opts.OpenCLVersion == 200); 40510b57cec5SDimitry Andric 405206c3fb27SDimitry Andric Opts.ConvergentFunctions = Args.hasArg(OPT_fconvergent_functions) || 405306c3fb27SDimitry Andric Opts.OpenCL || (Opts.CUDA && Opts.CUDAIsDevice) || 40540fca6ea1SDimitry Andric Opts.SYCLIsDevice || Opts.HLSL; 4055480093f4SDimitry Andric 40560b57cec5SDimitry Andric Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding; 40570b57cec5SDimitry Andric if (!Opts.NoBuiltin) 40580b57cec5SDimitry Andric getAllNoBuiltinFuncValues(Args, Opts.NoBuiltinFuncs); 405981ad6265SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_LongDouble_Group)) { 406081ad6265SDimitry Andric if (A->getOption().matches(options::OPT_mlong_double_64)) 406181ad6265SDimitry Andric Opts.LongDoubleSize = 64; 406281ad6265SDimitry Andric else if (A->getOption().matches(options::OPT_mlong_double_80)) 406381ad6265SDimitry Andric Opts.LongDoubleSize = 80; 406481ad6265SDimitry Andric else if (A->getOption().matches(options::OPT_mlong_double_128)) 406581ad6265SDimitry Andric Opts.LongDoubleSize = 128; 406681ad6265SDimitry Andric else 406781ad6265SDimitry Andric Opts.LongDoubleSize = 0; 406881ad6265SDimitry Andric } 4069bdd1243dSDimitry Andric if (Opts.FastRelaxedMath || Opts.CLUnsafeMath) 40705ffd83dbSDimitry Andric Opts.setDefaultFPContractMode(LangOptions::FPM_Fast); 407181ad6265SDimitry Andric 40720b57cec5SDimitry Andric llvm::sort(Opts.ModuleFeatures); 4073e8d8bef9SDimitry Andric 40740b57cec5SDimitry Andric // -mrtd option 40750b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(OPT_mrtd)) { 40760b57cec5SDimitry Andric if (Opts.getDefaultCallingConv() != LangOptions::DCC_None) 40770b57cec5SDimitry Andric Diags.Report(diag::err_drv_argument_not_allowed_with) 40780b57cec5SDimitry Andric << A->getSpelling() << "-fdefault-calling-conv"; 40790b57cec5SDimitry Andric else { 40805f757f3fSDimitry Andric switch (T.getArch()) { 40815f757f3fSDimitry Andric case llvm::Triple::x86: 40825f757f3fSDimitry Andric Opts.setDefaultCallingConv(LangOptions::DCC_StdCall); 40835f757f3fSDimitry Andric break; 40845f757f3fSDimitry Andric case llvm::Triple::m68k: 40855f757f3fSDimitry Andric Opts.setDefaultCallingConv(LangOptions::DCC_RtdCall); 40865f757f3fSDimitry Andric break; 40875f757f3fSDimitry Andric default: 40880b57cec5SDimitry Andric Diags.Report(diag::err_drv_argument_not_allowed_with) 40890b57cec5SDimitry Andric << A->getSpelling() << T.getTriple(); 40905f757f3fSDimitry Andric } 40910b57cec5SDimitry Andric } 40920b57cec5SDimitry Andric } 40930b57cec5SDimitry Andric 4094fe6060f1SDimitry Andric // Check if -fopenmp is specified and set default version to 5.0. 409506c3fb27SDimitry Andric Opts.OpenMP = Args.hasArg(OPT_fopenmp) ? 51 : 0; 40960b57cec5SDimitry Andric // Check if -fopenmp-simd is specified. 40970b57cec5SDimitry Andric bool IsSimdSpecified = 40980b57cec5SDimitry Andric Args.hasFlag(options::OPT_fopenmp_simd, options::OPT_fno_openmp_simd, 40990b57cec5SDimitry Andric /*Default=*/false); 41000b57cec5SDimitry Andric Opts.OpenMPSimd = !Opts.OpenMP && IsSimdSpecified; 41010b57cec5SDimitry Andric Opts.OpenMPUseTLS = 41020b57cec5SDimitry Andric Opts.OpenMP && !Args.hasArg(options::OPT_fnoopenmp_use_tls); 410306c3fb27SDimitry Andric Opts.OpenMPIsTargetDevice = 410406c3fb27SDimitry Andric Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_is_target_device); 4105480093f4SDimitry Andric Opts.OpenMPIRBuilder = 4106480093f4SDimitry Andric Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_enable_irbuilder); 41070b57cec5SDimitry Andric bool IsTargetSpecified = 410806c3fb27SDimitry Andric Opts.OpenMPIsTargetDevice || Args.hasArg(options::OPT_fopenmp_targets_EQ); 41090b57cec5SDimitry Andric 411006c3fb27SDimitry Andric Opts.ConvergentFunctions = 411106c3fb27SDimitry Andric Opts.ConvergentFunctions || Opts.OpenMPIsTargetDevice; 4112d409305fSDimitry Andric 41130b57cec5SDimitry Andric if (Opts.OpenMP || Opts.OpenMPSimd) { 41140b57cec5SDimitry Andric if (int Version = getLastArgIntValue( 41150b57cec5SDimitry Andric Args, OPT_fopenmp_version_EQ, 411606c3fb27SDimitry Andric (IsSimdSpecified || IsTargetSpecified) ? 51 : Opts.OpenMP, Diags)) 41170b57cec5SDimitry Andric Opts.OpenMP = Version; 41180b57cec5SDimitry Andric // Provide diagnostic when a given target is not expected to be an OpenMP 41190b57cec5SDimitry Andric // device or host. 412006c3fb27SDimitry Andric if (!Opts.OpenMPIsTargetDevice) { 41210b57cec5SDimitry Andric switch (T.getArch()) { 41220b57cec5SDimitry Andric default: 41230b57cec5SDimitry Andric break; 41240b57cec5SDimitry Andric // Add unsupported host targets here: 41250b57cec5SDimitry Andric case llvm::Triple::nvptx: 41260b57cec5SDimitry Andric case llvm::Triple::nvptx64: 4127e8d8bef9SDimitry Andric Diags.Report(diag::err_drv_omp_host_target_not_supported) << T.str(); 41280b57cec5SDimitry Andric break; 41290b57cec5SDimitry Andric } 41300b57cec5SDimitry Andric } 41310b57cec5SDimitry Andric } 41320b57cec5SDimitry Andric 41330b57cec5SDimitry Andric // Set the flag to prevent the implementation from emitting device exception 41340b57cec5SDimitry Andric // handling code for those requiring so. 413506c3fb27SDimitry Andric if ((Opts.OpenMPIsTargetDevice && (T.isNVPTX() || T.isAMDGCN())) || 41365ffd83dbSDimitry Andric Opts.OpenCLCPlusPlus) { 4137349cc55cSDimitry Andric 41380b57cec5SDimitry Andric Opts.Exceptions = 0; 41390b57cec5SDimitry Andric Opts.CXXExceptions = 0; 41400b57cec5SDimitry Andric } 414106c3fb27SDimitry Andric if (Opts.OpenMPIsTargetDevice && T.isNVPTX()) { 41420b57cec5SDimitry Andric Opts.OpenMPCUDANumSMs = 41430b57cec5SDimitry Andric getLastArgIntValue(Args, options::OPT_fopenmp_cuda_number_of_sm_EQ, 41440b57cec5SDimitry Andric Opts.OpenMPCUDANumSMs, Diags); 41450b57cec5SDimitry Andric Opts.OpenMPCUDABlocksPerSM = 41460b57cec5SDimitry Andric getLastArgIntValue(Args, options::OPT_fopenmp_cuda_blocks_per_sm_EQ, 41470b57cec5SDimitry Andric Opts.OpenMPCUDABlocksPerSM, Diags); 41480b57cec5SDimitry Andric Opts.OpenMPCUDAReductionBufNum = getLastArgIntValue( 41490b57cec5SDimitry Andric Args, options::OPT_fopenmp_cuda_teams_reduction_recs_num_EQ, 41500b57cec5SDimitry Andric Opts.OpenMPCUDAReductionBufNum, Diags); 41510b57cec5SDimitry Andric } 41520b57cec5SDimitry Andric 4153349cc55cSDimitry Andric // Set the value of the debugging flag used in the new offloading device RTL. 4154349cc55cSDimitry Andric // Set either by a specific value or to a default if not specified. 415506c3fb27SDimitry Andric if (Opts.OpenMPIsTargetDevice && (Args.hasArg(OPT_fopenmp_target_debug) || 4156349cc55cSDimitry Andric Args.hasArg(OPT_fopenmp_target_debug_EQ))) { 4157349cc55cSDimitry Andric Opts.OpenMPTargetDebug = getLastArgIntValue( 4158349cc55cSDimitry Andric Args, OPT_fopenmp_target_debug_EQ, Opts.OpenMPTargetDebug, Diags); 4159349cc55cSDimitry Andric if (!Opts.OpenMPTargetDebug && Args.hasArg(OPT_fopenmp_target_debug)) 4160349cc55cSDimitry Andric Opts.OpenMPTargetDebug = 1; 4161349cc55cSDimitry Andric } 4162349cc55cSDimitry Andric 416306c3fb27SDimitry Andric if (Opts.OpenMPIsTargetDevice) { 4164349cc55cSDimitry Andric if (Args.hasArg(OPT_fopenmp_assume_teams_oversubscription)) 4165349cc55cSDimitry Andric Opts.OpenMPTeamSubscription = true; 4166349cc55cSDimitry Andric if (Args.hasArg(OPT_fopenmp_assume_threads_oversubscription)) 4167349cc55cSDimitry Andric Opts.OpenMPThreadSubscription = true; 4168349cc55cSDimitry Andric } 4169349cc55cSDimitry Andric 41700b57cec5SDimitry Andric // Get the OpenMP target triples if any. 41710b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_fopenmp_targets_EQ)) { 4172e8d8bef9SDimitry Andric enum ArchPtrSize { Arch16Bit, Arch32Bit, Arch64Bit }; 4173e8d8bef9SDimitry Andric auto getArchPtrSize = [](const llvm::Triple &T) { 4174e8d8bef9SDimitry Andric if (T.isArch16Bit()) 4175e8d8bef9SDimitry Andric return Arch16Bit; 4176e8d8bef9SDimitry Andric if (T.isArch32Bit()) 4177e8d8bef9SDimitry Andric return Arch32Bit; 4178e8d8bef9SDimitry Andric assert(T.isArch64Bit() && "Expected 64-bit architecture"); 4179e8d8bef9SDimitry Andric return Arch64Bit; 4180e8d8bef9SDimitry Andric }; 41810b57cec5SDimitry Andric 41820b57cec5SDimitry Andric for (unsigned i = 0; i < A->getNumValues(); ++i) { 41830b57cec5SDimitry Andric llvm::Triple TT(A->getValue(i)); 41840b57cec5SDimitry Andric 41850b57cec5SDimitry Andric if (TT.getArch() == llvm::Triple::UnknownArch || 4186e8d8bef9SDimitry Andric !(TT.getArch() == llvm::Triple::aarch64 || TT.isPPC() || 41870fca6ea1SDimitry Andric TT.getArch() == llvm::Triple::systemz || 41880b57cec5SDimitry Andric TT.getArch() == llvm::Triple::nvptx || 41890b57cec5SDimitry Andric TT.getArch() == llvm::Triple::nvptx64 || 41905ffd83dbSDimitry Andric TT.getArch() == llvm::Triple::amdgcn || 41910b57cec5SDimitry Andric TT.getArch() == llvm::Triple::x86 || 41920b57cec5SDimitry Andric TT.getArch() == llvm::Triple::x86_64)) 41930b57cec5SDimitry Andric Diags.Report(diag::err_drv_invalid_omp_target) << A->getValue(i); 4194e8d8bef9SDimitry Andric else if (getArchPtrSize(T) != getArchPtrSize(TT)) 4195e8d8bef9SDimitry Andric Diags.Report(diag::err_drv_incompatible_omp_arch) 4196e8d8bef9SDimitry Andric << A->getValue(i) << T.str(); 41970b57cec5SDimitry Andric else 41980b57cec5SDimitry Andric Opts.OMPTargetTriples.push_back(TT); 41990b57cec5SDimitry Andric } 42000b57cec5SDimitry Andric } 42010b57cec5SDimitry Andric 42020b57cec5SDimitry Andric // Get OpenMP host file path if any and report if a non existent file is 42030b57cec5SDimitry Andric // found 42040b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_fopenmp_host_ir_file_path)) { 42050b57cec5SDimitry Andric Opts.OMPHostIRFile = A->getValue(); 42060b57cec5SDimitry Andric if (!llvm::sys::fs::exists(Opts.OMPHostIRFile)) 42070b57cec5SDimitry Andric Diags.Report(diag::err_drv_omp_host_ir_file_not_found) 42080b57cec5SDimitry Andric << Opts.OMPHostIRFile; 42090b57cec5SDimitry Andric } 42100b57cec5SDimitry Andric 42115ffd83dbSDimitry Andric // Set CUDA mode for OpenMP target NVPTX/AMDGCN if specified in options 421206c3fb27SDimitry Andric Opts.OpenMPCUDAMode = Opts.OpenMPIsTargetDevice && 421306c3fb27SDimitry Andric (T.isNVPTX() || T.isAMDGCN()) && 42140b57cec5SDimitry Andric Args.hasArg(options::OPT_fopenmp_cuda_mode); 42150b57cec5SDimitry Andric 42165f757f3fSDimitry Andric // OpenACC Configuration. 42175f757f3fSDimitry Andric if (Args.hasArg(options::OPT_fopenacc)) { 42185f757f3fSDimitry Andric Opts.OpenACC = true; 42195f757f3fSDimitry Andric 42205f757f3fSDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_openacc_macro_override)) 42215f757f3fSDimitry Andric Opts.OpenACCMacroOverride = A->getValue(); 42225f757f3fSDimitry Andric } 42235f757f3fSDimitry Andric 42240b57cec5SDimitry Andric // FIXME: Eliminate this dependency. 42250b57cec5SDimitry Andric unsigned Opt = getOptimizationLevel(Args, IK, Diags), 42260b57cec5SDimitry Andric OptSize = getOptimizationLevelSize(Args); 42270b57cec5SDimitry Andric Opts.Optimize = Opt != 0; 42280b57cec5SDimitry Andric Opts.OptimizeSize = OptSize != 0; 42290b57cec5SDimitry Andric 42300b57cec5SDimitry Andric // This is the __NO_INLINE__ define, which just depends on things like the 42310b57cec5SDimitry Andric // optimization level and -fno-inline, not actually whether the backend has 42320b57cec5SDimitry Andric // inlining enabled. 42330b57cec5SDimitry Andric Opts.NoInlineDefine = !Opts.Optimize; 42340b57cec5SDimitry Andric if (Arg *InlineArg = Args.getLastArg( 42350b57cec5SDimitry Andric options::OPT_finline_functions, options::OPT_finline_hint_functions, 42360b57cec5SDimitry Andric options::OPT_fno_inline_functions, options::OPT_fno_inline)) 42370b57cec5SDimitry Andric if (InlineArg->getOption().matches(options::OPT_fno_inline)) 42380b57cec5SDimitry Andric Opts.NoInlineDefine = true; 42390b57cec5SDimitry Andric 42400b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(OPT_ffp_contract)) { 42410b57cec5SDimitry Andric StringRef Val = A->getValue(); 42420b57cec5SDimitry Andric if (Val == "fast") 42435ffd83dbSDimitry Andric Opts.setDefaultFPContractMode(LangOptions::FPM_Fast); 42440b57cec5SDimitry Andric else if (Val == "on") 42455ffd83dbSDimitry Andric Opts.setDefaultFPContractMode(LangOptions::FPM_On); 42460b57cec5SDimitry Andric else if (Val == "off") 42475ffd83dbSDimitry Andric Opts.setDefaultFPContractMode(LangOptions::FPM_Off); 4248e8d8bef9SDimitry Andric else if (Val == "fast-honor-pragmas") 4249e8d8bef9SDimitry Andric Opts.setDefaultFPContractMode(LangOptions::FPM_FastHonorPragmas); 42500b57cec5SDimitry Andric else 42510b57cec5SDimitry Andric Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val; 42520b57cec5SDimitry Andric } 42530b57cec5SDimitry Andric 42540b57cec5SDimitry Andric // Parse -fsanitize= arguments. 42550b57cec5SDimitry Andric parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ), 42560b57cec5SDimitry Andric Diags, Opts.Sanitize); 4257fe6060f1SDimitry Andric Opts.NoSanitizeFiles = Args.getAllArgValues(OPT_fsanitize_ignorelist_EQ); 4258fe6060f1SDimitry Andric std::vector<std::string> systemIgnorelists = 4259fe6060f1SDimitry Andric Args.getAllArgValues(OPT_fsanitize_system_ignorelist_EQ); 4260fe6060f1SDimitry Andric Opts.NoSanitizeFiles.insert(Opts.NoSanitizeFiles.end(), 4261fe6060f1SDimitry Andric systemIgnorelists.begin(), 4262fe6060f1SDimitry Andric systemIgnorelists.end()); 42630b57cec5SDimitry Andric 42640b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(OPT_fclang_abi_compat_EQ)) { 42650b57cec5SDimitry Andric Opts.setClangABICompat(LangOptions::ClangABI::Latest); 42660b57cec5SDimitry Andric 42670b57cec5SDimitry Andric StringRef Ver = A->getValue(); 42680b57cec5SDimitry Andric std::pair<StringRef, StringRef> VerParts = Ver.split('.'); 42690b57cec5SDimitry Andric unsigned Major, Minor = 0; 42700b57cec5SDimitry Andric 42710b57cec5SDimitry Andric // Check the version number is valid: either 3.x (0 <= x <= 9) or 42720b57cec5SDimitry Andric // y or y.0 (4 <= y <= current version). 42735f757f3fSDimitry Andric if (!VerParts.first.starts_with("0") && 42745f757f3fSDimitry Andric !VerParts.first.getAsInteger(10, Major) && 3 <= Major && 42755f757f3fSDimitry Andric Major <= CLANG_VERSION_MAJOR && 42765f757f3fSDimitry Andric (Major == 3 42775f757f3fSDimitry Andric ? VerParts.second.size() == 1 && 42780b57cec5SDimitry Andric !VerParts.second.getAsInteger(10, Minor) 42795f757f3fSDimitry Andric : VerParts.first.size() == Ver.size() || VerParts.second == "0")) { 42800b57cec5SDimitry Andric // Got a valid version number. 42810b57cec5SDimitry Andric if (Major == 3 && Minor <= 8) 42820b57cec5SDimitry Andric Opts.setClangABICompat(LangOptions::ClangABI::Ver3_8); 42830b57cec5SDimitry Andric else if (Major <= 4) 42840b57cec5SDimitry Andric Opts.setClangABICompat(LangOptions::ClangABI::Ver4); 42850b57cec5SDimitry Andric else if (Major <= 6) 42860b57cec5SDimitry Andric Opts.setClangABICompat(LangOptions::ClangABI::Ver6); 42870b57cec5SDimitry Andric else if (Major <= 7) 42880b57cec5SDimitry Andric Opts.setClangABICompat(LangOptions::ClangABI::Ver7); 4289a7dea167SDimitry Andric else if (Major <= 9) 4290a7dea167SDimitry Andric Opts.setClangABICompat(LangOptions::ClangABI::Ver9); 4291e8d8bef9SDimitry Andric else if (Major <= 11) 4292e8d8bef9SDimitry Andric Opts.setClangABICompat(LangOptions::ClangABI::Ver11); 4293fe6060f1SDimitry Andric else if (Major <= 12) 4294fe6060f1SDimitry Andric Opts.setClangABICompat(LangOptions::ClangABI::Ver12); 429581ad6265SDimitry Andric else if (Major <= 14) 429681ad6265SDimitry Andric Opts.setClangABICompat(LangOptions::ClangABI::Ver14); 4297bdd1243dSDimitry Andric else if (Major <= 15) 4298bdd1243dSDimitry Andric Opts.setClangABICompat(LangOptions::ClangABI::Ver15); 42995f757f3fSDimitry Andric else if (Major <= 17) 43005f757f3fSDimitry Andric Opts.setClangABICompat(LangOptions::ClangABI::Ver17); 43010fca6ea1SDimitry Andric else if (Major <= 18) 43020fca6ea1SDimitry Andric Opts.setClangABICompat(LangOptions::ClangABI::Ver18); 43030b57cec5SDimitry Andric } else if (Ver != "latest") { 43040b57cec5SDimitry Andric Diags.Report(diag::err_drv_invalid_value) 43050b57cec5SDimitry Andric << A->getAsString(Args) << A->getValue(); 43060b57cec5SDimitry Andric } 43070b57cec5SDimitry Andric } 43080b57cec5SDimitry Andric 43095ffd83dbSDimitry Andric if (Arg *A = Args.getLastArg(OPT_msign_return_address_EQ)) { 43105ffd83dbSDimitry Andric StringRef SignScope = A->getValue(); 43115ffd83dbSDimitry Andric 4312fe6060f1SDimitry Andric if (SignScope.equals_insensitive("none")) 43135ffd83dbSDimitry Andric Opts.setSignReturnAddressScope( 43145ffd83dbSDimitry Andric LangOptions::SignReturnAddressScopeKind::None); 4315fe6060f1SDimitry Andric else if (SignScope.equals_insensitive("all")) 43165ffd83dbSDimitry Andric Opts.setSignReturnAddressScope( 43175ffd83dbSDimitry Andric LangOptions::SignReturnAddressScopeKind::All); 4318fe6060f1SDimitry Andric else if (SignScope.equals_insensitive("non-leaf")) 43195ffd83dbSDimitry Andric Opts.setSignReturnAddressScope( 43205ffd83dbSDimitry Andric LangOptions::SignReturnAddressScopeKind::NonLeaf); 43215ffd83dbSDimitry Andric else 43225ffd83dbSDimitry Andric Diags.Report(diag::err_drv_invalid_value) 43235ffd83dbSDimitry Andric << A->getAsString(Args) << SignScope; 43245ffd83dbSDimitry Andric 43255ffd83dbSDimitry Andric if (Arg *A = Args.getLastArg(OPT_msign_return_address_key_EQ)) { 43265ffd83dbSDimitry Andric StringRef SignKey = A->getValue(); 43275ffd83dbSDimitry Andric if (!SignScope.empty() && !SignKey.empty()) { 43285f757f3fSDimitry Andric if (SignKey == "a_key") 43295ffd83dbSDimitry Andric Opts.setSignReturnAddressKey( 43305ffd83dbSDimitry Andric LangOptions::SignReturnAddressKeyKind::AKey); 43315f757f3fSDimitry Andric else if (SignKey == "b_key") 43325ffd83dbSDimitry Andric Opts.setSignReturnAddressKey( 43335ffd83dbSDimitry Andric LangOptions::SignReturnAddressKeyKind::BKey); 43345ffd83dbSDimitry Andric else 43355ffd83dbSDimitry Andric Diags.Report(diag::err_drv_invalid_value) 43365ffd83dbSDimitry Andric << A->getAsString(Args) << SignKey; 43375ffd83dbSDimitry Andric } 43385ffd83dbSDimitry Andric } 43395ffd83dbSDimitry Andric } 43405ffd83dbSDimitry Andric 4341fe6060f1SDimitry Andric // The value can be empty, which indicates the system default should be used. 4342fe6060f1SDimitry Andric StringRef CXXABI = Args.getLastArgValue(OPT_fcxx_abi_EQ); 4343fe6060f1SDimitry Andric if (!CXXABI.empty()) { 4344fe6060f1SDimitry Andric if (!TargetCXXABI::isABI(CXXABI)) { 4345fe6060f1SDimitry Andric Diags.Report(diag::err_invalid_cxx_abi) << CXXABI; 4346fe6060f1SDimitry Andric } else { 4347fe6060f1SDimitry Andric auto Kind = TargetCXXABI::getKind(CXXABI); 4348fe6060f1SDimitry Andric if (!TargetCXXABI::isSupportedCXXABI(T, Kind)) 4349fe6060f1SDimitry Andric Diags.Report(diag::err_unsupported_cxx_abi) << CXXABI << T.str(); 4350fe6060f1SDimitry Andric else 4351fe6060f1SDimitry Andric Opts.CXXABI = Kind; 4352fe6060f1SDimitry Andric } 4353fe6060f1SDimitry Andric } 4354fe6060f1SDimitry Andric 4355fe6060f1SDimitry Andric Opts.RelativeCXXABIVTables = 4356fe6060f1SDimitry Andric Args.hasFlag(options::OPT_fexperimental_relative_cxx_abi_vtables, 4357fe6060f1SDimitry Andric options::OPT_fno_experimental_relative_cxx_abi_vtables, 4358fe6060f1SDimitry Andric TargetCXXABI::usesRelativeVTables(T)); 4359fe6060f1SDimitry Andric 43605f757f3fSDimitry Andric // RTTI is on by default. 43615f757f3fSDimitry Andric bool HasRTTI = !Args.hasArg(options::OPT_fno_rtti); 43625f757f3fSDimitry Andric Opts.OmitVTableRTTI = 43635f757f3fSDimitry Andric Args.hasFlag(options::OPT_fexperimental_omit_vtable_rtti, 43645f757f3fSDimitry Andric options::OPT_fno_experimental_omit_vtable_rtti, false); 43655f757f3fSDimitry Andric if (Opts.OmitVTableRTTI && HasRTTI) 43665f757f3fSDimitry Andric Diags.Report(diag::err_drv_using_omit_rtti_component_without_no_rtti); 43675f757f3fSDimitry Andric 43686e75b2fbSDimitry Andric for (const auto &A : Args.getAllArgValues(OPT_fmacro_prefix_map_EQ)) { 43696e75b2fbSDimitry Andric auto Split = StringRef(A).split('='); 43706e75b2fbSDimitry Andric Opts.MacroPrefixMap.insert( 43716e75b2fbSDimitry Andric {std::string(Split.first), std::string(Split.second)}); 43726e75b2fbSDimitry Andric } 43736e75b2fbSDimitry Andric 437481ad6265SDimitry Andric Opts.UseTargetPathSeparator = 437581ad6265SDimitry Andric !Args.getLastArg(OPT_fno_file_reproducible) && 437681ad6265SDimitry Andric (Args.getLastArg(OPT_ffile_compilation_dir_EQ) || 437781ad6265SDimitry Andric Args.getLastArg(OPT_fmacro_prefix_map_EQ) || 437881ad6265SDimitry Andric Args.getLastArg(OPT_ffile_reproducible)); 437981ad6265SDimitry Andric 43800eae32dcSDimitry Andric // Error if -mvscale-min is unbounded. 43810eae32dcSDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_mvscale_min_EQ)) { 43820eae32dcSDimitry Andric unsigned VScaleMin; 43830eae32dcSDimitry Andric if (StringRef(A->getValue()).getAsInteger(10, VScaleMin) || VScaleMin == 0) 43840eae32dcSDimitry Andric Diags.Report(diag::err_cc1_unbounded_vscale_min); 43850eae32dcSDimitry Andric } 43860eae32dcSDimitry Andric 438781ad6265SDimitry Andric if (const Arg *A = Args.getLastArg(OPT_frandomize_layout_seed_file_EQ)) { 438881ad6265SDimitry Andric std::ifstream SeedFile(A->getValue(0)); 438981ad6265SDimitry Andric 439081ad6265SDimitry Andric if (!SeedFile.is_open()) 439181ad6265SDimitry Andric Diags.Report(diag::err_drv_cannot_open_randomize_layout_seed_file) 439281ad6265SDimitry Andric << A->getValue(0); 439381ad6265SDimitry Andric 439481ad6265SDimitry Andric std::getline(SeedFile, Opts.RandstructSeed); 439581ad6265SDimitry Andric } 439681ad6265SDimitry Andric 439781ad6265SDimitry Andric if (const Arg *A = Args.getLastArg(OPT_frandomize_layout_seed_EQ)) 439881ad6265SDimitry Andric Opts.RandstructSeed = A->getValue(0); 439981ad6265SDimitry Andric 4400bdd1243dSDimitry Andric // Validate options for HLSL 4401bdd1243dSDimitry Andric if (Opts.HLSL) { 44025f757f3fSDimitry Andric // TODO: Revisit restricting SPIR-V to logical once we've figured out how to 44035f757f3fSDimitry Andric // handle PhysicalStorageBuffer64 memory model 44045f757f3fSDimitry Andric if (T.isDXIL() || T.isSPIRVLogical()) { 44057a6dacacSDimitry Andric enum { ShaderModel, VulkanEnv, ShaderStage }; 44067a6dacacSDimitry Andric enum { OS, Environment }; 44077a6dacacSDimitry Andric 44087a6dacacSDimitry Andric int ExpectedOS = T.isSPIRVLogical() ? VulkanEnv : ShaderModel; 44097a6dacacSDimitry Andric 44105f757f3fSDimitry Andric if (T.getOSName().empty()) { 44115f757f3fSDimitry Andric Diags.Report(diag::err_drv_hlsl_bad_shader_required_in_target) 44127a6dacacSDimitry Andric << ExpectedOS << OS << T.str(); 44135f757f3fSDimitry Andric } else if (T.getEnvironmentName().empty()) { 44145f757f3fSDimitry Andric Diags.Report(diag::err_drv_hlsl_bad_shader_required_in_target) 44157a6dacacSDimitry Andric << ShaderStage << Environment << T.str(); 44165f757f3fSDimitry Andric } else if (!T.isShaderStageEnvironment()) { 44175f757f3fSDimitry Andric Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported) 44185f757f3fSDimitry Andric << ShaderStage << T.getEnvironmentName() << T.str(); 44195f757f3fSDimitry Andric } 44207a6dacacSDimitry Andric 44217a6dacacSDimitry Andric if (T.isDXIL()) { 44227a6dacacSDimitry Andric if (!T.isShaderModelOS() || T.getOSVersion() == VersionTuple(0)) { 44237a6dacacSDimitry Andric Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported) 44247a6dacacSDimitry Andric << ShaderModel << T.getOSName() << T.str(); 44257a6dacacSDimitry Andric } 44260fca6ea1SDimitry Andric // Validate that if fnative-half-type is given, that 44270fca6ea1SDimitry Andric // the language standard is at least hlsl2018, and that 44280fca6ea1SDimitry Andric // the target shader model is at least 6.2. 44290fca6ea1SDimitry Andric if (Args.getLastArg(OPT_fnative_half_type)) { 44300fca6ea1SDimitry Andric const LangStandard &Std = 44310fca6ea1SDimitry Andric LangStandard::getLangStandardForKind(Opts.LangStd); 44320fca6ea1SDimitry Andric if (!(Opts.LangStd >= LangStandard::lang_hlsl2018 && 44330fca6ea1SDimitry Andric T.getOSVersion() >= VersionTuple(6, 2))) 44340fca6ea1SDimitry Andric Diags.Report(diag::err_drv_hlsl_16bit_types_unsupported) 44350fca6ea1SDimitry Andric << "-enable-16bit-types" << true << Std.getName() 44360fca6ea1SDimitry Andric << T.getOSVersion().getAsString(); 44370fca6ea1SDimitry Andric } 44387a6dacacSDimitry Andric } else if (T.isSPIRVLogical()) { 44397a6dacacSDimitry Andric if (!T.isVulkanOS() || T.getVulkanVersion() == VersionTuple(0)) { 44407a6dacacSDimitry Andric Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported) 44417a6dacacSDimitry Andric << VulkanEnv << T.getOSName() << T.str(); 44427a6dacacSDimitry Andric } 44430fca6ea1SDimitry Andric if (Args.getLastArg(OPT_fnative_half_type)) { 44440fca6ea1SDimitry Andric const LangStandard &Std = 44450fca6ea1SDimitry Andric LangStandard::getLangStandardForKind(Opts.LangStd); 44460fca6ea1SDimitry Andric if (!(Opts.LangStd >= LangStandard::lang_hlsl2018)) 44470fca6ea1SDimitry Andric Diags.Report(diag::err_drv_hlsl_16bit_types_unsupported) 44480fca6ea1SDimitry Andric << "-fnative-half-type" << false << Std.getName(); 44490fca6ea1SDimitry Andric } 44507a6dacacSDimitry Andric } else { 44517a6dacacSDimitry Andric llvm_unreachable("expected DXIL or SPIR-V target"); 44527a6dacacSDimitry Andric } 44535f757f3fSDimitry Andric } else 4454bdd1243dSDimitry Andric Diags.Report(diag::err_drv_hlsl_unsupported_target) << T.str(); 4455bdd1243dSDimitry Andric } 4456bdd1243dSDimitry Andric 4457fe6060f1SDimitry Andric return Diags.getNumErrors() == NumErrorsBefore; 44580b57cec5SDimitry Andric } 44590b57cec5SDimitry Andric 44600b57cec5SDimitry Andric static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { 44610b57cec5SDimitry Andric switch (Action) { 44620b57cec5SDimitry Andric case frontend::ASTDeclList: 44630b57cec5SDimitry Andric case frontend::ASTDump: 44640b57cec5SDimitry Andric case frontend::ASTPrint: 44650b57cec5SDimitry Andric case frontend::ASTView: 44660b57cec5SDimitry Andric case frontend::EmitAssembly: 44670b57cec5SDimitry Andric case frontend::EmitBC: 44680fca6ea1SDimitry Andric case frontend::EmitCIR: 44690b57cec5SDimitry Andric case frontend::EmitHTML: 44700b57cec5SDimitry Andric case frontend::EmitLLVM: 44710b57cec5SDimitry Andric case frontend::EmitLLVMOnly: 44720b57cec5SDimitry Andric case frontend::EmitCodeGenOnly: 44730b57cec5SDimitry Andric case frontend::EmitObj: 447404eeddc0SDimitry Andric case frontend::ExtractAPI: 44750b57cec5SDimitry Andric case frontend::FixIt: 44760b57cec5SDimitry Andric case frontend::GenerateModule: 44770b57cec5SDimitry Andric case frontend::GenerateModuleInterface: 44780fca6ea1SDimitry Andric case frontend::GenerateReducedModuleInterface: 447981ad6265SDimitry Andric case frontend::GenerateHeaderUnit: 44800b57cec5SDimitry Andric case frontend::GeneratePCH: 44815ffd83dbSDimitry Andric case frontend::GenerateInterfaceStubs: 44820b57cec5SDimitry Andric case frontend::ParseSyntaxOnly: 44830b57cec5SDimitry Andric case frontend::ModuleFileInfo: 44840b57cec5SDimitry Andric case frontend::VerifyPCH: 44850b57cec5SDimitry Andric case frontend::PluginAction: 44860b57cec5SDimitry Andric case frontend::RewriteObjC: 44870b57cec5SDimitry Andric case frontend::RewriteTest: 44880b57cec5SDimitry Andric case frontend::RunAnalysis: 44890b57cec5SDimitry Andric case frontend::TemplightDump: 44900b57cec5SDimitry Andric case frontend::MigrateSource: 44910b57cec5SDimitry Andric return false; 44920b57cec5SDimitry Andric 44930b57cec5SDimitry Andric case frontend::DumpCompilerOptions: 44940b57cec5SDimitry Andric case frontend::DumpRawTokens: 44950b57cec5SDimitry Andric case frontend::DumpTokens: 44960b57cec5SDimitry Andric case frontend::InitOnly: 44970b57cec5SDimitry Andric case frontend::PrintPreamble: 44980b57cec5SDimitry Andric case frontend::PrintPreprocessedInput: 44990b57cec5SDimitry Andric case frontend::RewriteMacros: 45000b57cec5SDimitry Andric case frontend::RunPreprocessorOnly: 45010b57cec5SDimitry Andric case frontend::PrintDependencyDirectivesSourceMinimizerOutput: 45020b57cec5SDimitry Andric return true; 45030b57cec5SDimitry Andric } 45040b57cec5SDimitry Andric llvm_unreachable("invalid frontend action"); 45050b57cec5SDimitry Andric } 45060b57cec5SDimitry Andric 45075f757f3fSDimitry Andric static void GeneratePreprocessorArgs(const PreprocessorOptions &Opts, 45085f757f3fSDimitry Andric ArgumentConsumer Consumer, 4509fe6060f1SDimitry Andric const LangOptions &LangOpts, 4510fe6060f1SDimitry Andric const FrontendOptions &FrontendOpts, 4511fe6060f1SDimitry Andric const CodeGenOptions &CodeGenOpts) { 45125f757f3fSDimitry Andric const PreprocessorOptions *PreprocessorOpts = &Opts; 4513fe6060f1SDimitry Andric 451406c3fb27SDimitry Andric #define PREPROCESSOR_OPTION_WITH_MARSHALLING(...) \ 45155f757f3fSDimitry Andric GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__) 4516fe6060f1SDimitry Andric #include "clang/Driver/Options.inc" 4517fe6060f1SDimitry Andric #undef PREPROCESSOR_OPTION_WITH_MARSHALLING 4518fe6060f1SDimitry Andric 4519fe6060f1SDimitry Andric if (Opts.PCHWithHdrStop && !Opts.PCHWithHdrStopCreate) 45205f757f3fSDimitry Andric GenerateArg(Consumer, OPT_pch_through_hdrstop_use); 4521fe6060f1SDimitry Andric 4522fe6060f1SDimitry Andric for (const auto &D : Opts.DeserializedPCHDeclsToErrorOn) 45235f757f3fSDimitry Andric GenerateArg(Consumer, OPT_error_on_deserialized_pch_decl, D); 4524fe6060f1SDimitry Andric 4525fe6060f1SDimitry Andric if (Opts.PrecompiledPreambleBytes != std::make_pair(0u, false)) 45265f757f3fSDimitry Andric GenerateArg(Consumer, OPT_preamble_bytes_EQ, 4527fe6060f1SDimitry Andric Twine(Opts.PrecompiledPreambleBytes.first) + "," + 45285f757f3fSDimitry Andric (Opts.PrecompiledPreambleBytes.second ? "1" : "0")); 4529fe6060f1SDimitry Andric 4530fe6060f1SDimitry Andric for (const auto &M : Opts.Macros) { 4531fe6060f1SDimitry Andric // Don't generate __CET__ macro definitions. They are implied by the 4532fe6060f1SDimitry Andric // -fcf-protection option that is generated elsewhere. 4533fe6060f1SDimitry Andric if (M.first == "__CET__=1" && !M.second && 4534fe6060f1SDimitry Andric !CodeGenOpts.CFProtectionReturn && CodeGenOpts.CFProtectionBranch) 4535fe6060f1SDimitry Andric continue; 4536fe6060f1SDimitry Andric if (M.first == "__CET__=2" && !M.second && CodeGenOpts.CFProtectionReturn && 4537fe6060f1SDimitry Andric !CodeGenOpts.CFProtectionBranch) 4538fe6060f1SDimitry Andric continue; 4539fe6060f1SDimitry Andric if (M.first == "__CET__=3" && !M.second && CodeGenOpts.CFProtectionReturn && 4540fe6060f1SDimitry Andric CodeGenOpts.CFProtectionBranch) 4541fe6060f1SDimitry Andric continue; 4542fe6060f1SDimitry Andric 45435f757f3fSDimitry Andric GenerateArg(Consumer, M.second ? OPT_U : OPT_D, M.first); 4544fe6060f1SDimitry Andric } 4545fe6060f1SDimitry Andric 4546fe6060f1SDimitry Andric for (const auto &I : Opts.Includes) { 4547fe6060f1SDimitry Andric // Don't generate OpenCL includes. They are implied by other flags that are 4548fe6060f1SDimitry Andric // generated elsewhere. 4549fe6060f1SDimitry Andric if (LangOpts.OpenCL && LangOpts.IncludeDefaultHeader && 4550fe6060f1SDimitry Andric ((LangOpts.DeclareOpenCLBuiltins && I == "opencl-c-base.h") || 4551fe6060f1SDimitry Andric I == "opencl-c.h")) 4552fe6060f1SDimitry Andric continue; 455381ad6265SDimitry Andric // Don't generate HLSL includes. They are implied by other flags that are 455481ad6265SDimitry Andric // generated elsewhere. 455581ad6265SDimitry Andric if (LangOpts.HLSL && I == "hlsl.h") 455681ad6265SDimitry Andric continue; 4557fe6060f1SDimitry Andric 45585f757f3fSDimitry Andric GenerateArg(Consumer, OPT_include, I); 4559fe6060f1SDimitry Andric } 4560fe6060f1SDimitry Andric 4561fe6060f1SDimitry Andric for (const auto &CI : Opts.ChainedIncludes) 45625f757f3fSDimitry Andric GenerateArg(Consumer, OPT_chain_include, CI); 4563fe6060f1SDimitry Andric 4564fe6060f1SDimitry Andric for (const auto &RF : Opts.RemappedFiles) 45655f757f3fSDimitry Andric GenerateArg(Consumer, OPT_remap_file, RF.first + ";" + RF.second); 4566fe6060f1SDimitry Andric 4567bdd1243dSDimitry Andric if (Opts.SourceDateEpoch) 45685f757f3fSDimitry Andric GenerateArg(Consumer, OPT_source_date_epoch, Twine(*Opts.SourceDateEpoch)); 45695f757f3fSDimitry Andric 45705f757f3fSDimitry Andric if (Opts.DefineTargetOSMacros) 45715f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fdefine_target_os_macros); 4572bdd1243dSDimitry Andric 45730fca6ea1SDimitry Andric for (const auto &EmbedEntry : Opts.EmbedEntries) 45740fca6ea1SDimitry Andric GenerateArg(Consumer, OPT_embed_dir_EQ, EmbedEntry); 45750fca6ea1SDimitry Andric 4576fe6060f1SDimitry Andric // Don't handle LexEditorPlaceholders. It is implied by the action that is 4577fe6060f1SDimitry Andric // generated elsewhere. 4578fe6060f1SDimitry Andric } 4579fe6060f1SDimitry Andric 4580fe6060f1SDimitry Andric static bool ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, 45810b57cec5SDimitry Andric DiagnosticsEngine &Diags, 4582fe6060f1SDimitry Andric frontend::ActionKind Action, 4583fe6060f1SDimitry Andric const FrontendOptions &FrontendOpts) { 4584fe6060f1SDimitry Andric unsigned NumErrorsBefore = Diags.getNumErrors(); 4585fe6060f1SDimitry Andric 4586fe6060f1SDimitry Andric PreprocessorOptions *PreprocessorOpts = &Opts; 4587fe6060f1SDimitry Andric 458806c3fb27SDimitry Andric #define PREPROCESSOR_OPTION_WITH_MARSHALLING(...) \ 458906c3fb27SDimitry Andric PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__) 4590fe6060f1SDimitry Andric #include "clang/Driver/Options.inc" 4591fe6060f1SDimitry Andric #undef PREPROCESSOR_OPTION_WITH_MARSHALLING 4592fe6060f1SDimitry Andric 45930b57cec5SDimitry Andric Opts.PCHWithHdrStop = Args.hasArg(OPT_pch_through_hdrstop_create) || 45940b57cec5SDimitry Andric Args.hasArg(OPT_pch_through_hdrstop_use); 45950b57cec5SDimitry Andric 45960b57cec5SDimitry Andric for (const auto *A : Args.filtered(OPT_error_on_deserialized_pch_decl)) 45970b57cec5SDimitry Andric Opts.DeserializedPCHDeclsToErrorOn.insert(A->getValue()); 45980b57cec5SDimitry Andric 45990b57cec5SDimitry Andric if (const Arg *A = Args.getLastArg(OPT_preamble_bytes_EQ)) { 46000b57cec5SDimitry Andric StringRef Value(A->getValue()); 46010b57cec5SDimitry Andric size_t Comma = Value.find(','); 46020b57cec5SDimitry Andric unsigned Bytes = 0; 46030b57cec5SDimitry Andric unsigned EndOfLine = 0; 46040b57cec5SDimitry Andric 46050b57cec5SDimitry Andric if (Comma == StringRef::npos || 46060b57cec5SDimitry Andric Value.substr(0, Comma).getAsInteger(10, Bytes) || 46070b57cec5SDimitry Andric Value.substr(Comma + 1).getAsInteger(10, EndOfLine)) 46080b57cec5SDimitry Andric Diags.Report(diag::err_drv_preamble_format); 46090b57cec5SDimitry Andric else { 46100b57cec5SDimitry Andric Opts.PrecompiledPreambleBytes.first = Bytes; 46110b57cec5SDimitry Andric Opts.PrecompiledPreambleBytes.second = (EndOfLine != 0); 46120b57cec5SDimitry Andric } 46130b57cec5SDimitry Andric } 46140b57cec5SDimitry Andric 46150b57cec5SDimitry Andric // Add the __CET__ macro if a CFProtection option is set. 46160b57cec5SDimitry Andric if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) { 46170b57cec5SDimitry Andric StringRef Name = A->getValue(); 46180b57cec5SDimitry Andric if (Name == "branch") 46190b57cec5SDimitry Andric Opts.addMacroDef("__CET__=1"); 46200b57cec5SDimitry Andric else if (Name == "return") 46210b57cec5SDimitry Andric Opts.addMacroDef("__CET__=2"); 46220b57cec5SDimitry Andric else if (Name == "full") 46230b57cec5SDimitry Andric Opts.addMacroDef("__CET__=3"); 46240b57cec5SDimitry Andric } 46250b57cec5SDimitry Andric 46260b57cec5SDimitry Andric // Add macros from the command line. 46270b57cec5SDimitry Andric for (const auto *A : Args.filtered(OPT_D, OPT_U)) { 46280b57cec5SDimitry Andric if (A->getOption().matches(OPT_D)) 46290b57cec5SDimitry Andric Opts.addMacroDef(A->getValue()); 46300b57cec5SDimitry Andric else 46310b57cec5SDimitry Andric Opts.addMacroUndef(A->getValue()); 46320b57cec5SDimitry Andric } 46330b57cec5SDimitry Andric 46340b57cec5SDimitry Andric // Add the ordered list of -includes. 46350b57cec5SDimitry Andric for (const auto *A : Args.filtered(OPT_include)) 46360b57cec5SDimitry Andric Opts.Includes.emplace_back(A->getValue()); 46370b57cec5SDimitry Andric 46380b57cec5SDimitry Andric for (const auto *A : Args.filtered(OPT_chain_include)) 46390b57cec5SDimitry Andric Opts.ChainedIncludes.emplace_back(A->getValue()); 46400b57cec5SDimitry Andric 46410b57cec5SDimitry Andric for (const auto *A : Args.filtered(OPT_remap_file)) { 46420b57cec5SDimitry Andric std::pair<StringRef, StringRef> Split = StringRef(A->getValue()).split(';'); 46430b57cec5SDimitry Andric 46440b57cec5SDimitry Andric if (Split.second.empty()) { 46450b57cec5SDimitry Andric Diags.Report(diag::err_drv_invalid_remap_file) << A->getAsString(Args); 46460b57cec5SDimitry Andric continue; 46470b57cec5SDimitry Andric } 46480b57cec5SDimitry Andric 46490b57cec5SDimitry Andric Opts.addRemappedFile(Split.first, Split.second); 46500b57cec5SDimitry Andric } 46510b57cec5SDimitry Andric 4652bdd1243dSDimitry Andric if (const Arg *A = Args.getLastArg(OPT_source_date_epoch)) { 4653bdd1243dSDimitry Andric StringRef Epoch = A->getValue(); 4654bdd1243dSDimitry Andric // SOURCE_DATE_EPOCH, if specified, must be a non-negative decimal integer. 4655bdd1243dSDimitry Andric // On time64 systems, pick 253402300799 (the UNIX timestamp of 4656bdd1243dSDimitry Andric // 9999-12-31T23:59:59Z) as the upper bound. 4657bdd1243dSDimitry Andric const uint64_t MaxTimestamp = 4658bdd1243dSDimitry Andric std::min<uint64_t>(std::numeric_limits<time_t>::max(), 253402300799); 4659bdd1243dSDimitry Andric uint64_t V; 4660bdd1243dSDimitry Andric if (Epoch.getAsInteger(10, V) || V > MaxTimestamp) { 4661bdd1243dSDimitry Andric Diags.Report(diag::err_fe_invalid_source_date_epoch) 4662bdd1243dSDimitry Andric << Epoch << MaxTimestamp; 4663bdd1243dSDimitry Andric } else { 4664bdd1243dSDimitry Andric Opts.SourceDateEpoch = V; 4665bdd1243dSDimitry Andric } 4666bdd1243dSDimitry Andric } 4667bdd1243dSDimitry Andric 46680fca6ea1SDimitry Andric for (const auto *A : Args.filtered(OPT_embed_dir_EQ)) { 46690fca6ea1SDimitry Andric StringRef Val = A->getValue(); 46700fca6ea1SDimitry Andric Opts.EmbedEntries.push_back(std::string(Val)); 46710fca6ea1SDimitry Andric } 46720fca6ea1SDimitry Andric 46730b57cec5SDimitry Andric // Always avoid lexing editor placeholders when we're just running the 46740b57cec5SDimitry Andric // preprocessor as we never want to emit the 46750b57cec5SDimitry Andric // "editor placeholder in source file" error in PP only mode. 46760b57cec5SDimitry Andric if (isStrictlyPreprocessorAction(Action)) 46770b57cec5SDimitry Andric Opts.LexEditorPlaceholders = false; 4678fe6060f1SDimitry Andric 46795f757f3fSDimitry Andric Opts.DefineTargetOSMacros = 46805f757f3fSDimitry Andric Args.hasFlag(OPT_fdefine_target_os_macros, 46815f757f3fSDimitry Andric OPT_fno_define_target_os_macros, Opts.DefineTargetOSMacros); 46825f757f3fSDimitry Andric 4683fe6060f1SDimitry Andric return Diags.getNumErrors() == NumErrorsBefore; 46840b57cec5SDimitry Andric } 46850b57cec5SDimitry Andric 46865f757f3fSDimitry Andric static void 46875f757f3fSDimitry Andric GeneratePreprocessorOutputArgs(const PreprocessorOutputOptions &Opts, 46885f757f3fSDimitry Andric ArgumentConsumer Consumer, 46895f757f3fSDimitry Andric frontend::ActionKind Action) { 4690fe6060f1SDimitry Andric const PreprocessorOutputOptions &PreprocessorOutputOpts = Opts; 4691fe6060f1SDimitry Andric 469206c3fb27SDimitry Andric #define PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING(...) \ 46935f757f3fSDimitry Andric GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__) 4694fe6060f1SDimitry Andric #include "clang/Driver/Options.inc" 4695fe6060f1SDimitry Andric #undef PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING 4696fe6060f1SDimitry Andric 4697fe6060f1SDimitry Andric bool Generate_dM = isStrictlyPreprocessorAction(Action) && !Opts.ShowCPP; 4698fe6060f1SDimitry Andric if (Generate_dM) 46995f757f3fSDimitry Andric GenerateArg(Consumer, OPT_dM); 4700fe6060f1SDimitry Andric if (!Generate_dM && Opts.ShowMacros) 47015f757f3fSDimitry Andric GenerateArg(Consumer, OPT_dD); 470281ad6265SDimitry Andric if (Opts.DirectivesOnly) 47035f757f3fSDimitry Andric GenerateArg(Consumer, OPT_fdirectives_only); 4704fe6060f1SDimitry Andric } 4705fe6060f1SDimitry Andric 4706fe6060f1SDimitry Andric static bool ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, 4707fe6060f1SDimitry Andric ArgList &Args, DiagnosticsEngine &Diags, 47080b57cec5SDimitry Andric frontend::ActionKind Action) { 4709fe6060f1SDimitry Andric unsigned NumErrorsBefore = Diags.getNumErrors(); 47100b57cec5SDimitry Andric 4711fe6060f1SDimitry Andric PreprocessorOutputOptions &PreprocessorOutputOpts = Opts; 4712fe6060f1SDimitry Andric 471306c3fb27SDimitry Andric #define PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING(...) \ 471406c3fb27SDimitry Andric PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__) 4715fe6060f1SDimitry Andric #include "clang/Driver/Options.inc" 4716fe6060f1SDimitry Andric #undef PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING 4717fe6060f1SDimitry Andric 4718fe6060f1SDimitry Andric Opts.ShowCPP = isStrictlyPreprocessorAction(Action) && !Args.hasArg(OPT_dM); 47190b57cec5SDimitry Andric Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD); 472081ad6265SDimitry Andric Opts.DirectivesOnly = Args.hasArg(OPT_fdirectives_only); 4721fe6060f1SDimitry Andric 4722fe6060f1SDimitry Andric return Diags.getNumErrors() == NumErrorsBefore; 47230b57cec5SDimitry Andric } 47240b57cec5SDimitry Andric 4725fe6060f1SDimitry Andric static void GenerateTargetArgs(const TargetOptions &Opts, 47265f757f3fSDimitry Andric ArgumentConsumer Consumer) { 4727fe6060f1SDimitry Andric const TargetOptions *TargetOpts = &Opts; 472806c3fb27SDimitry Andric #define TARGET_OPTION_WITH_MARSHALLING(...) \ 47295f757f3fSDimitry Andric GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__) 4730fe6060f1SDimitry Andric #include "clang/Driver/Options.inc" 4731fe6060f1SDimitry Andric #undef TARGET_OPTION_WITH_MARSHALLING 4732fe6060f1SDimitry Andric 4733fe6060f1SDimitry Andric if (!Opts.SDKVersion.empty()) 47345f757f3fSDimitry Andric GenerateArg(Consumer, OPT_target_sdk_version_EQ, 47355f757f3fSDimitry Andric Opts.SDKVersion.getAsString()); 473681ad6265SDimitry Andric if (!Opts.DarwinTargetVariantSDKVersion.empty()) 47375f757f3fSDimitry Andric GenerateArg(Consumer, OPT_darwin_target_variant_sdk_version_EQ, 47385f757f3fSDimitry Andric Opts.DarwinTargetVariantSDKVersion.getAsString()); 4739fe6060f1SDimitry Andric } 4740fe6060f1SDimitry Andric 4741fe6060f1SDimitry Andric static bool ParseTargetArgs(TargetOptions &Opts, ArgList &Args, 47420b57cec5SDimitry Andric DiagnosticsEngine &Diags) { 4743fe6060f1SDimitry Andric unsigned NumErrorsBefore = Diags.getNumErrors(); 4744fe6060f1SDimitry Andric 4745fe6060f1SDimitry Andric TargetOptions *TargetOpts = &Opts; 4746fe6060f1SDimitry Andric 474706c3fb27SDimitry Andric #define TARGET_OPTION_WITH_MARSHALLING(...) \ 474806c3fb27SDimitry Andric PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__) 4749fe6060f1SDimitry Andric #include "clang/Driver/Options.inc" 4750fe6060f1SDimitry Andric #undef TARGET_OPTION_WITH_MARSHALLING 4751fe6060f1SDimitry Andric 47520b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_target_sdk_version_EQ)) { 47530b57cec5SDimitry Andric llvm::VersionTuple Version; 47540b57cec5SDimitry Andric if (Version.tryParse(A->getValue())) 47550b57cec5SDimitry Andric Diags.Report(diag::err_drv_invalid_value) 47560b57cec5SDimitry Andric << A->getAsString(Args) << A->getValue(); 47570b57cec5SDimitry Andric else 47580b57cec5SDimitry Andric Opts.SDKVersion = Version; 47590b57cec5SDimitry Andric } 476081ad6265SDimitry Andric if (Arg *A = 476181ad6265SDimitry Andric Args.getLastArg(options::OPT_darwin_target_variant_sdk_version_EQ)) { 476281ad6265SDimitry Andric llvm::VersionTuple Version; 476381ad6265SDimitry Andric if (Version.tryParse(A->getValue())) 476481ad6265SDimitry Andric Diags.Report(diag::err_drv_invalid_value) 476581ad6265SDimitry Andric << A->getAsString(Args) << A->getValue(); 476681ad6265SDimitry Andric else 476781ad6265SDimitry Andric Opts.DarwinTargetVariantSDKVersion = Version; 476881ad6265SDimitry Andric } 4769fe6060f1SDimitry Andric 4770fe6060f1SDimitry Andric return Diags.getNumErrors() == NumErrorsBefore; 47710b57cec5SDimitry Andric } 47720b57cec5SDimitry Andric 4773fe6060f1SDimitry Andric bool CompilerInvocation::CreateFromArgsImpl( 4774fe6060f1SDimitry Andric CompilerInvocation &Res, ArrayRef<const char *> CommandLineArgs, 4775fe6060f1SDimitry Andric DiagnosticsEngine &Diags, const char *Argv0) { 4776fe6060f1SDimitry Andric unsigned NumErrorsBefore = Diags.getNumErrors(); 47770b57cec5SDimitry Andric 47780b57cec5SDimitry Andric // Parse the arguments. 4779a7dea167SDimitry Andric const OptTable &Opts = getDriverOptTable(); 47805f757f3fSDimitry Andric llvm::opt::Visibility VisibilityMask(options::CC1Option); 47810b57cec5SDimitry Andric unsigned MissingArgIndex, MissingArgCount; 4782a7dea167SDimitry Andric InputArgList Args = Opts.ParseArgs(CommandLineArgs, MissingArgIndex, 47835f757f3fSDimitry Andric MissingArgCount, VisibilityMask); 47845f757f3fSDimitry Andric LangOptions &LangOpts = Res.getLangOpts(); 47850b57cec5SDimitry Andric 47860b57cec5SDimitry Andric // Check for missing argument error. 4787fe6060f1SDimitry Andric if (MissingArgCount) 47880b57cec5SDimitry Andric Diags.Report(diag::err_drv_missing_argument) 47890b57cec5SDimitry Andric << Args.getArgString(MissingArgIndex) << MissingArgCount; 47900b57cec5SDimitry Andric 47910b57cec5SDimitry Andric // Issue errors on unknown arguments. 47920b57cec5SDimitry Andric for (const auto *A : Args.filtered(OPT_UNKNOWN)) { 47930b57cec5SDimitry Andric auto ArgString = A->getAsString(Args); 47940b57cec5SDimitry Andric std::string Nearest; 47955f757f3fSDimitry Andric if (Opts.findNearest(ArgString, Nearest, VisibilityMask) > 1) 47960b57cec5SDimitry Andric Diags.Report(diag::err_drv_unknown_argument) << ArgString; 47970b57cec5SDimitry Andric else 47980b57cec5SDimitry Andric Diags.Report(diag::err_drv_unknown_argument_with_suggestion) 47990b57cec5SDimitry Andric << ArgString << Nearest; 48000b57cec5SDimitry Andric } 48010b57cec5SDimitry Andric 4802fe6060f1SDimitry Andric ParseFileSystemArgs(Res.getFileSystemOpts(), Args, Diags); 4803fe6060f1SDimitry Andric ParseMigratorArgs(Res.getMigratorOpts(), Args, Diags); 48045f757f3fSDimitry Andric ParseAnalyzerArgs(Res.getAnalyzerOpts(), Args, Diags); 4805fe6060f1SDimitry Andric ParseDiagnosticArgs(Res.getDiagnosticOpts(), Args, &Diags, 48065ffd83dbSDimitry Andric /*DefaultDiagColor=*/false); 4807fe6060f1SDimitry Andric ParseFrontendArgs(Res.getFrontendOpts(), Args, Diags, LangOpts.IsHeaderFile); 48080b57cec5SDimitry Andric // FIXME: We shouldn't have to pass the DashX option around here 4809fe6060f1SDimitry Andric InputKind DashX = Res.getFrontendOpts().DashX; 48100b57cec5SDimitry Andric ParseTargetArgs(Res.getTargetOpts(), Args, Diags); 4811e8d8bef9SDimitry Andric llvm::Triple T(Res.getTargetOpts().Triple); 4812fe6060f1SDimitry Andric ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args, Diags, 48130b57cec5SDimitry Andric Res.getFileSystemOpts().WorkingDir); 48145f757f3fSDimitry Andric ParseAPINotesArgs(Res.getAPINotesOpts(), Args, Diags); 4815fe6060f1SDimitry Andric 48160fca6ea1SDimitry Andric ParsePointerAuthArgs(LangOpts, Args, Diags); 48170fca6ea1SDimitry Andric 4818e8d8bef9SDimitry Andric ParseLangArgs(LangOpts, Args, DashX, T, Res.getPreprocessorOpts().Includes, 4819e8d8bef9SDimitry Andric Diags); 48200b57cec5SDimitry Andric if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC) 48210b57cec5SDimitry Andric LangOpts.ObjCExceptions = 1; 48220b57cec5SDimitry Andric 482381ad6265SDimitry Andric for (auto Warning : Res.getDiagnosticOpts().Warnings) { 482481ad6265SDimitry Andric if (Warning == "misexpect" && 482581ad6265SDimitry Andric !Diags.isIgnored(diag::warn_profile_data_misexpect, SourceLocation())) { 482681ad6265SDimitry Andric Res.getCodeGenOpts().MisExpect = true; 482781ad6265SDimitry Andric } 482881ad6265SDimitry Andric } 482981ad6265SDimitry Andric 48300b57cec5SDimitry Andric if (LangOpts.CUDA) { 48310b57cec5SDimitry Andric // During CUDA device-side compilation, the aux triple is the 48320b57cec5SDimitry Andric // triple used for host compilation. 48330b57cec5SDimitry Andric if (LangOpts.CUDAIsDevice) 48340b57cec5SDimitry Andric Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple; 48350b57cec5SDimitry Andric } 48360b57cec5SDimitry Andric 48370b57cec5SDimitry Andric // Set the triple of the host for OpenMP device compile. 483806c3fb27SDimitry Andric if (LangOpts.OpenMPIsTargetDevice) 48390b57cec5SDimitry Andric Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple; 48400b57cec5SDimitry Andric 4841fe6060f1SDimitry Andric ParseCodeGenArgs(Res.getCodeGenOpts(), Args, DashX, Diags, T, 4842e8d8bef9SDimitry Andric Res.getFrontendOpts().OutputFile, LangOpts); 4843e8d8bef9SDimitry Andric 48440b57cec5SDimitry Andric // FIXME: Override value name discarding when asan or msan is used because the 48450b57cec5SDimitry Andric // backend passes depend on the name of the alloca in order to print out 48460b57cec5SDimitry Andric // names. 48470b57cec5SDimitry Andric Res.getCodeGenOpts().DiscardValueNames &= 48480b57cec5SDimitry Andric !LangOpts.Sanitize.has(SanitizerKind::Address) && 48490b57cec5SDimitry Andric !LangOpts.Sanitize.has(SanitizerKind::KernelAddress) && 48500b57cec5SDimitry Andric !LangOpts.Sanitize.has(SanitizerKind::Memory) && 48510b57cec5SDimitry Andric !LangOpts.Sanitize.has(SanitizerKind::KernelMemory); 48520b57cec5SDimitry Andric 48530b57cec5SDimitry Andric ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, Diags, 4854fe6060f1SDimitry Andric Res.getFrontendOpts().ProgramAction, 4855fe6060f1SDimitry Andric Res.getFrontendOpts()); 4856fe6060f1SDimitry Andric ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), Args, Diags, 48570b57cec5SDimitry Andric Res.getFrontendOpts().ProgramAction); 48580b57cec5SDimitry Andric 4859fe6060f1SDimitry Andric ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), Args, Diags, 4860fe6060f1SDimitry Andric Res.getFrontendOpts().ProgramAction, 4861fe6060f1SDimitry Andric Res.getPreprocessorOutputOpts().ShowLineMarkers); 4862fe6060f1SDimitry Andric if (!Res.getDependencyOutputOpts().OutputFile.empty() && 4863fe6060f1SDimitry Andric Res.getDependencyOutputOpts().Targets.empty()) 4864fe6060f1SDimitry Andric Diags.Report(diag::err_fe_dependency_file_requires_MT); 48650b57cec5SDimitry Andric 48660b57cec5SDimitry Andric // If sanitizer is enabled, disable OPT_ffine_grained_bitfield_accesses. 48670b57cec5SDimitry Andric if (Res.getCodeGenOpts().FineGrainedBitfieldAccesses && 48685f757f3fSDimitry Andric !Res.getLangOpts().Sanitize.empty()) { 48690b57cec5SDimitry Andric Res.getCodeGenOpts().FineGrainedBitfieldAccesses = false; 48700b57cec5SDimitry Andric Diags.Report(diag::warn_drv_fine_grained_bitfield_accesses_ignored); 48710b57cec5SDimitry Andric } 48725ffd83dbSDimitry Andric 48735ffd83dbSDimitry Andric // Store the command-line for using in the CodeView backend. 4874bdd1243dSDimitry Andric if (Res.getCodeGenOpts().CodeViewCommandLine) { 48755ffd83dbSDimitry Andric Res.getCodeGenOpts().Argv0 = Argv0; 48760eae32dcSDimitry Andric append_range(Res.getCodeGenOpts().CommandLineArgs, CommandLineArgs); 4877bdd1243dSDimitry Andric } 48785ffd83dbSDimitry Andric 487906c3fb27SDimitry Andric // Set PGOOptions. Need to create a temporary VFS to read the profile 488006c3fb27SDimitry Andric // to determine the PGO type. 488106c3fb27SDimitry Andric if (!Res.getCodeGenOpts().ProfileInstrumentUsePath.empty()) { 488206c3fb27SDimitry Andric auto FS = 488306c3fb27SDimitry Andric createVFSFromOverlayFiles(Res.getHeaderSearchOpts().VFSOverlayFiles, 488406c3fb27SDimitry Andric Diags, llvm::vfs::getRealFileSystem()); 488506c3fb27SDimitry Andric setPGOUseInstrumentor(Res.getCodeGenOpts(), 488606c3fb27SDimitry Andric Res.getCodeGenOpts().ProfileInstrumentUsePath, *FS, 488706c3fb27SDimitry Andric Diags); 488806c3fb27SDimitry Andric } 488906c3fb27SDimitry Andric 4890e8d8bef9SDimitry Andric FixupInvocation(Res, Diags, Args, DashX); 4891e8d8bef9SDimitry Andric 4892fe6060f1SDimitry Andric return Diags.getNumErrors() == NumErrorsBefore; 4893fe6060f1SDimitry Andric } 4894fe6060f1SDimitry Andric 4895fe6060f1SDimitry Andric bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Invocation, 4896fe6060f1SDimitry Andric ArrayRef<const char *> CommandLineArgs, 4897fe6060f1SDimitry Andric DiagnosticsEngine &Diags, 4898fe6060f1SDimitry Andric const char *Argv0) { 4899fe6060f1SDimitry Andric CompilerInvocation DummyInvocation; 4900fe6060f1SDimitry Andric 4901fe6060f1SDimitry Andric return RoundTrip( 4902fe6060f1SDimitry Andric [](CompilerInvocation &Invocation, ArrayRef<const char *> CommandLineArgs, 4903fe6060f1SDimitry Andric DiagnosticsEngine &Diags, const char *Argv0) { 4904fe6060f1SDimitry Andric return CreateFromArgsImpl(Invocation, CommandLineArgs, Diags, Argv0); 4905fe6060f1SDimitry Andric }, 4906fe6060f1SDimitry Andric [](CompilerInvocation &Invocation, SmallVectorImpl<const char *> &Args, 4907bdd1243dSDimitry Andric StringAllocator SA) { 4908bdd1243dSDimitry Andric Args.push_back("-cc1"); 4909bdd1243dSDimitry Andric Invocation.generateCC1CommandLine(Args, SA); 4910bdd1243dSDimitry Andric }, 4911fe6060f1SDimitry Andric Invocation, DummyInvocation, CommandLineArgs, Diags, Argv0); 49120b57cec5SDimitry Andric } 49130b57cec5SDimitry Andric 49140b57cec5SDimitry Andric std::string CompilerInvocation::getModuleHash() const { 4915349cc55cSDimitry Andric // FIXME: Consider using SHA1 instead of MD5. 49165f757f3fSDimitry Andric llvm::HashBuilder<llvm::MD5, llvm::endianness::native> HBuilder; 4917349cc55cSDimitry Andric 49180b57cec5SDimitry Andric // Note: For QoI reasons, the things we use as a hash here should all be 49190b57cec5SDimitry Andric // dumped via the -module-info flag. 49200b57cec5SDimitry Andric 49210b57cec5SDimitry Andric // Start the signature with the compiler version. 4922349cc55cSDimitry Andric HBuilder.add(getClangFullRepositoryVersion()); 49230b57cec5SDimitry Andric 49245ffd83dbSDimitry Andric // Also include the serialization version, in case LLVM_APPEND_VC_REV is off 49255ffd83dbSDimitry Andric // and getClangFullRepositoryVersion() doesn't include git revision. 4926349cc55cSDimitry Andric HBuilder.add(serialization::VERSION_MAJOR, serialization::VERSION_MINOR); 49275ffd83dbSDimitry Andric 49280b57cec5SDimitry Andric // Extend the signature with the language options 4929349cc55cSDimitry Andric #define LANGOPT(Name, Bits, Default, Description) HBuilder.add(LangOpts->Name); 49300b57cec5SDimitry Andric #define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ 4931349cc55cSDimitry Andric HBuilder.add(static_cast<unsigned>(LangOpts->get##Name())); 49320b57cec5SDimitry Andric #define BENIGN_LANGOPT(Name, Bits, Default, Description) 49330b57cec5SDimitry Andric #define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) 49340b57cec5SDimitry Andric #include "clang/Basic/LangOptions.def" 49350b57cec5SDimitry Andric 49365f757f3fSDimitry Andric HBuilder.addRange(getLangOpts().ModuleFeatures); 49370b57cec5SDimitry Andric 49385f757f3fSDimitry Andric HBuilder.add(getLangOpts().ObjCRuntime); 49395f757f3fSDimitry Andric HBuilder.addRange(getLangOpts().CommentOpts.BlockCommandNames); 49405ffd83dbSDimitry Andric 49410b57cec5SDimitry Andric // Extend the signature with the target options. 49425f757f3fSDimitry Andric HBuilder.add(getTargetOpts().Triple, getTargetOpts().CPU, 49435f757f3fSDimitry Andric getTargetOpts().TuneCPU, getTargetOpts().ABI); 49445f757f3fSDimitry Andric HBuilder.addRange(getTargetOpts().FeaturesAsWritten); 49450b57cec5SDimitry Andric 49460b57cec5SDimitry Andric // Extend the signature with preprocessor options. 49470b57cec5SDimitry Andric const PreprocessorOptions &ppOpts = getPreprocessorOpts(); 4948349cc55cSDimitry Andric HBuilder.add(ppOpts.UsePredefines, ppOpts.DetailedRecord); 49490b57cec5SDimitry Andric 4950349cc55cSDimitry Andric const HeaderSearchOptions &hsOpts = getHeaderSearchOpts(); 4951349cc55cSDimitry Andric for (const auto &Macro : getPreprocessorOpts().Macros) { 49520b57cec5SDimitry Andric // If we're supposed to ignore this macro for the purposes of modules, 49530b57cec5SDimitry Andric // don't put it into the hash. 49540b57cec5SDimitry Andric if (!hsOpts.ModulesIgnoreMacros.empty()) { 49550b57cec5SDimitry Andric // Check whether we're ignoring this macro. 4956349cc55cSDimitry Andric StringRef MacroDef = Macro.first; 49570b57cec5SDimitry Andric if (hsOpts.ModulesIgnoreMacros.count( 49580b57cec5SDimitry Andric llvm::CachedHashString(MacroDef.split('=').first))) 49590b57cec5SDimitry Andric continue; 49600b57cec5SDimitry Andric } 49610b57cec5SDimitry Andric 4962349cc55cSDimitry Andric HBuilder.add(Macro); 49630b57cec5SDimitry Andric } 49640b57cec5SDimitry Andric 49650b57cec5SDimitry Andric // Extend the signature with the sysroot and other header search options. 4966349cc55cSDimitry Andric HBuilder.add(hsOpts.Sysroot, hsOpts.ModuleFormat, hsOpts.UseDebugInfo, 4967349cc55cSDimitry Andric hsOpts.UseBuiltinIncludes, hsOpts.UseStandardSystemIncludes, 4968349cc55cSDimitry Andric hsOpts.UseStandardCXXIncludes, hsOpts.UseLibcxx, 49690b57cec5SDimitry Andric hsOpts.ModulesValidateDiagnosticOptions); 4970349cc55cSDimitry Andric HBuilder.add(hsOpts.ResourceDir); 49710b57cec5SDimitry Andric 4972a7dea167SDimitry Andric if (hsOpts.ModulesStrictContextHash) { 4973349cc55cSDimitry Andric HBuilder.addRange(hsOpts.SystemHeaderPrefixes); 4974349cc55cSDimitry Andric HBuilder.addRange(hsOpts.UserEntries); 49750fca6ea1SDimitry Andric HBuilder.addRange(hsOpts.VFSOverlayFiles); 4976a7dea167SDimitry Andric 4977a7dea167SDimitry Andric const DiagnosticOptions &diagOpts = getDiagnosticOpts(); 4978349cc55cSDimitry Andric #define DIAGOPT(Name, Bits, Default) HBuilder.add(diagOpts.Name); 4979a7dea167SDimitry Andric #define ENUM_DIAGOPT(Name, Type, Bits, Default) \ 4980349cc55cSDimitry Andric HBuilder.add(diagOpts.get##Name()); 4981a7dea167SDimitry Andric #include "clang/Basic/DiagnosticOptions.def" 4982a7dea167SDimitry Andric #undef DIAGOPT 4983a7dea167SDimitry Andric #undef ENUM_DIAGOPT 4984a7dea167SDimitry Andric } 4985a7dea167SDimitry Andric 49860b57cec5SDimitry Andric // Extend the signature with the user build path. 4987349cc55cSDimitry Andric HBuilder.add(hsOpts.ModuleUserBuildPath); 49880b57cec5SDimitry Andric 49890b57cec5SDimitry Andric // Extend the signature with the module file extensions. 4990349cc55cSDimitry Andric for (const auto &ext : getFrontendOpts().ModuleFileExtensions) 4991349cc55cSDimitry Andric ext->hashExtension(HBuilder); 49920b57cec5SDimitry Andric 49935f757f3fSDimitry Andric // Extend the signature with the Swift version for API notes. 49945f757f3fSDimitry Andric const APINotesOptions &APINotesOpts = getAPINotesOpts(); 49955f757f3fSDimitry Andric if (!APINotesOpts.SwiftVersion.empty()) { 49965f757f3fSDimitry Andric HBuilder.add(APINotesOpts.SwiftVersion.getMajor()); 49975f757f3fSDimitry Andric if (auto Minor = APINotesOpts.SwiftVersion.getMinor()) 49985f757f3fSDimitry Andric HBuilder.add(*Minor); 49995f757f3fSDimitry Andric if (auto Subminor = APINotesOpts.SwiftVersion.getSubminor()) 50005f757f3fSDimitry Andric HBuilder.add(*Subminor); 50015f757f3fSDimitry Andric if (auto Build = APINotesOpts.SwiftVersion.getBuild()) 50025f757f3fSDimitry Andric HBuilder.add(*Build); 50035f757f3fSDimitry Andric } 50045f757f3fSDimitry Andric 50050b57cec5SDimitry Andric // When compiling with -gmodules, also hash -fdebug-prefix-map as it 50060b57cec5SDimitry Andric // affects the debug info in the PCM. 50070b57cec5SDimitry Andric if (getCodeGenOpts().DebugTypeExtRefs) 5008349cc55cSDimitry Andric HBuilder.addRange(getCodeGenOpts().DebugPrefixMap); 50090b57cec5SDimitry Andric 50105f757f3fSDimitry Andric // Extend the signature with the affecting debug options. 50115f757f3fSDimitry Andric if (getHeaderSearchOpts().ModuleFormat == "obj") { 50125f757f3fSDimitry Andric #define DEBUGOPT(Name, Bits, Default) HBuilder.add(CodeGenOpts->Name); 50135f757f3fSDimitry Andric #define VALUE_DEBUGOPT(Name, Bits, Default) HBuilder.add(CodeGenOpts->Name); 50145f757f3fSDimitry Andric #define ENUM_DEBUGOPT(Name, Type, Bits, Default) \ 50155f757f3fSDimitry Andric HBuilder.add(static_cast<unsigned>(CodeGenOpts->get##Name())); 50165f757f3fSDimitry Andric #define BENIGN_DEBUGOPT(Name, Bits, Default) 50175f757f3fSDimitry Andric #define BENIGN_VALUE_DEBUGOPT(Name, Bits, Default) 50185f757f3fSDimitry Andric #define BENIGN_ENUM_DEBUGOPT(Name, Type, Bits, Default) 50195f757f3fSDimitry Andric #include "clang/Basic/DebugOptions.def" 50205f757f3fSDimitry Andric } 50215f757f3fSDimitry Andric 50220b57cec5SDimitry Andric // Extend the signature with the enabled sanitizers, if at least one is 50230b57cec5SDimitry Andric // enabled. Sanitizers which cannot affect AST generation aren't hashed. 50245f757f3fSDimitry Andric SanitizerSet SanHash = getLangOpts().Sanitize; 50250b57cec5SDimitry Andric SanHash.clear(getPPTransparentSanitizers()); 50260b57cec5SDimitry Andric if (!SanHash.empty()) 5027349cc55cSDimitry Andric HBuilder.add(SanHash.Mask); 50280b57cec5SDimitry Andric 5029349cc55cSDimitry Andric llvm::MD5::MD5Result Result; 5030349cc55cSDimitry Andric HBuilder.getHasher().final(Result); 5031349cc55cSDimitry Andric uint64_t Hash = Result.high() ^ Result.low(); 5032349cc55cSDimitry Andric return toString(llvm::APInt(64, Hash), 36, /*Signed=*/false); 50330b57cec5SDimitry Andric } 50340b57cec5SDimitry Andric 50355f757f3fSDimitry Andric void CompilerInvocationBase::generateCC1CommandLine( 50365f757f3fSDimitry Andric ArgumentConsumer Consumer) const { 50375f757f3fSDimitry Andric llvm::Triple T(getTargetOpts().Triple); 50385ffd83dbSDimitry Andric 50395f757f3fSDimitry Andric GenerateFileSystemArgs(getFileSystemOpts(), Consumer); 50405f757f3fSDimitry Andric GenerateMigratorArgs(getMigratorOpts(), Consumer); 50415f757f3fSDimitry Andric GenerateAnalyzerArgs(getAnalyzerOpts(), Consumer); 50425f757f3fSDimitry Andric GenerateDiagnosticArgs(getDiagnosticOpts(), Consumer, 50435f757f3fSDimitry Andric /*DefaultDiagColor=*/false); 50445f757f3fSDimitry Andric GenerateFrontendArgs(getFrontendOpts(), Consumer, getLangOpts().IsHeaderFile); 50455f757f3fSDimitry Andric GenerateTargetArgs(getTargetOpts(), Consumer); 50465f757f3fSDimitry Andric GenerateHeaderSearchArgs(getHeaderSearchOpts(), Consumer); 50475f757f3fSDimitry Andric GenerateAPINotesArgs(getAPINotesOpts(), Consumer); 50480fca6ea1SDimitry Andric GeneratePointerAuthArgs(getLangOpts(), Consumer); 50495f757f3fSDimitry Andric GenerateLangArgs(getLangOpts(), Consumer, T, getFrontendOpts().DashX); 50505f757f3fSDimitry Andric GenerateCodeGenArgs(getCodeGenOpts(), Consumer, T, 50515f757f3fSDimitry Andric getFrontendOpts().OutputFile, &getLangOpts()); 50525f757f3fSDimitry Andric GeneratePreprocessorArgs(getPreprocessorOpts(), Consumer, getLangOpts(), 50535f757f3fSDimitry Andric getFrontendOpts(), getCodeGenOpts()); 50545f757f3fSDimitry Andric GeneratePreprocessorOutputArgs(getPreprocessorOutputOpts(), Consumer, 50555f757f3fSDimitry Andric getFrontendOpts().ProgramAction); 50565f757f3fSDimitry Andric GenerateDependencyOutputArgs(getDependencyOutputOpts(), Consumer); 50575ffd83dbSDimitry Andric } 50585ffd83dbSDimitry Andric 50595f757f3fSDimitry Andric std::vector<std::string> CompilerInvocationBase::getCC1CommandLine() const { 50605f757f3fSDimitry Andric std::vector<std::string> Args{"-cc1"}; 50615f757f3fSDimitry Andric generateCC1CommandLine( 50625f757f3fSDimitry Andric [&Args](const Twine &Arg) { Args.push_back(Arg.str()); }); 50635f757f3fSDimitry Andric return Args; 5064bdd1243dSDimitry Andric } 5065bdd1243dSDimitry Andric 5066bdd1243dSDimitry Andric void CompilerInvocation::resetNonModularOptions() { 50675f757f3fSDimitry Andric getLangOpts().resetNonModularOptions(); 5068bdd1243dSDimitry Andric getPreprocessorOpts().resetNonModularOptions(); 50695f757f3fSDimitry Andric getCodeGenOpts().resetNonModularOptions(getHeaderSearchOpts().ModuleFormat); 5070bdd1243dSDimitry Andric } 5071bdd1243dSDimitry Andric 5072bdd1243dSDimitry Andric void CompilerInvocation::clearImplicitModuleBuildOptions() { 50735f757f3fSDimitry Andric getLangOpts().ImplicitModules = false; 5074bdd1243dSDimitry Andric getHeaderSearchOpts().ImplicitModuleMaps = false; 5075bdd1243dSDimitry Andric getHeaderSearchOpts().ModuleCachePath.clear(); 5076bdd1243dSDimitry Andric getHeaderSearchOpts().ModulesValidateOncePerBuildSession = false; 5077bdd1243dSDimitry Andric getHeaderSearchOpts().BuildSessionTimestamp = 0; 5078bdd1243dSDimitry Andric // The specific values we canonicalize to for pruning don't affect behaviour, 5079bdd1243dSDimitry Andric /// so use the default values so they may be dropped from the command-line. 5080bdd1243dSDimitry Andric getHeaderSearchOpts().ModuleCachePruneInterval = 7 * 24 * 60 * 60; 5081bdd1243dSDimitry Andric getHeaderSearchOpts().ModuleCachePruneAfter = 31 * 24 * 60 * 60; 5082bdd1243dSDimitry Andric } 5083bdd1243dSDimitry Andric 50840b57cec5SDimitry Andric IntrusiveRefCntPtr<llvm::vfs::FileSystem> 5085e8d8bef9SDimitry Andric clang::createVFSFromCompilerInvocation(const CompilerInvocation &CI, 50860b57cec5SDimitry Andric DiagnosticsEngine &Diags) { 50870b57cec5SDimitry Andric return createVFSFromCompilerInvocation(CI, Diags, 50880b57cec5SDimitry Andric llvm::vfs::getRealFileSystem()); 50890b57cec5SDimitry Andric } 50900b57cec5SDimitry Andric 5091e8d8bef9SDimitry Andric IntrusiveRefCntPtr<llvm::vfs::FileSystem> 5092e8d8bef9SDimitry Andric clang::createVFSFromCompilerInvocation( 50930b57cec5SDimitry Andric const CompilerInvocation &CI, DiagnosticsEngine &Diags, 50940b57cec5SDimitry Andric IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS) { 5095bdd1243dSDimitry Andric return createVFSFromOverlayFiles(CI.getHeaderSearchOpts().VFSOverlayFiles, 5096bdd1243dSDimitry Andric Diags, std::move(BaseFS)); 5097bdd1243dSDimitry Andric } 5098bdd1243dSDimitry Andric 5099bdd1243dSDimitry Andric IntrusiveRefCntPtr<llvm::vfs::FileSystem> clang::createVFSFromOverlayFiles( 5100bdd1243dSDimitry Andric ArrayRef<std::string> VFSOverlayFiles, DiagnosticsEngine &Diags, 5101bdd1243dSDimitry Andric IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS) { 5102bdd1243dSDimitry Andric if (VFSOverlayFiles.empty()) 51030b57cec5SDimitry Andric return BaseFS; 51040b57cec5SDimitry Andric 51050b57cec5SDimitry Andric IntrusiveRefCntPtr<llvm::vfs::FileSystem> Result = BaseFS; 51060b57cec5SDimitry Andric // earlier vfs files are on the bottom 5107bdd1243dSDimitry Andric for (const auto &File : VFSOverlayFiles) { 51080b57cec5SDimitry Andric llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer = 51090b57cec5SDimitry Andric Result->getBufferForFile(File); 51100b57cec5SDimitry Andric if (!Buffer) { 51110b57cec5SDimitry Andric Diags.Report(diag::err_missing_vfs_overlay_file) << File; 51120b57cec5SDimitry Andric continue; 51130b57cec5SDimitry Andric } 51140b57cec5SDimitry Andric 51150b57cec5SDimitry Andric IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = llvm::vfs::getVFSFromYAML( 51160b57cec5SDimitry Andric std::move(Buffer.get()), /*DiagHandler*/ nullptr, File, 51170b57cec5SDimitry Andric /*DiagContext*/ nullptr, Result); 51180b57cec5SDimitry Andric if (!FS) { 51190b57cec5SDimitry Andric Diags.Report(diag::err_invalid_vfs_overlay) << File; 51200b57cec5SDimitry Andric continue; 51210b57cec5SDimitry Andric } 51220b57cec5SDimitry Andric 51230b57cec5SDimitry Andric Result = FS; 51240b57cec5SDimitry Andric } 51250b57cec5SDimitry Andric return Result; 51260b57cec5SDimitry Andric } 5127