xref: /src/contrib/llvm-project/clang/lib/Frontend/CompilerInvocation.cpp (revision 62987288060ff68c817b7056815aa9fb8ba8ecd7)
148675466SDimitry Andric //===- CompilerInvocation.cpp ---------------------------------------------===//
2b3d5a323SRoman Divacky //
322989816SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
422989816SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
522989816SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b3d5a323SRoman Divacky //
7b3d5a323SRoman Divacky //===----------------------------------------------------------------------===//
8b3d5a323SRoman Divacky 
9bab175ecSDimitry Andric #include "clang/Frontend/CompilerInvocation.h"
1045b53394SDimitry Andric #include "TestModuleFileExtension.h"
1197b17066SDimitry Andric #include "clang/Basic/Builtins.h"
1248675466SDimitry Andric #include "clang/Basic/CharInfo.h"
13676fbe81SDimitry Andric #include "clang/Basic/CodeGenOptions.h"
1448675466SDimitry Andric #include "clang/Basic/CommentOptions.h"
1548675466SDimitry Andric #include "clang/Basic/Diagnostic.h"
16b60736ecSDimitry Andric #include "clang/Basic/DiagnosticDriver.h"
1748675466SDimitry Andric #include "clang/Basic/DiagnosticOptions.h"
1848675466SDimitry Andric #include "clang/Basic/FileSystemOptions.h"
1948675466SDimitry Andric #include "clang/Basic/LLVM.h"
2048675466SDimitry Andric #include "clang/Basic/LangOptions.h"
21519fc96cSDimitry Andric #include "clang/Basic/LangStandard.h"
2248675466SDimitry Andric #include "clang/Basic/ObjCRuntime.h"
2348675466SDimitry Andric #include "clang/Basic/Sanitizers.h"
2448675466SDimitry Andric #include "clang/Basic/SourceLocation.h"
2548675466SDimitry Andric #include "clang/Basic/TargetOptions.h"
26809500fcSDimitry Andric #include "clang/Basic/Version.h"
2748675466SDimitry Andric #include "clang/Basic/Visibility.h"
2848675466SDimitry Andric #include "clang/Basic/XRayInstr.h"
2906d4ba38SDimitry Andric #include "clang/Config/config.h"
3022989816SDimitry Andric #include "clang/Driver/Driver.h"
311569ce68SRoman Divacky #include "clang/Driver/DriverDiagnostic.h"
32809500fcSDimitry Andric #include "clang/Driver/Options.h"
3348675466SDimitry Andric #include "clang/Frontend/CommandLineSourceLoc.h"
3448675466SDimitry Andric #include "clang/Frontend/DependencyOutputOptions.h"
359f4dbff6SDimitry Andric #include "clang/Frontend/FrontendDiagnostic.h"
3648675466SDimitry Andric #include "clang/Frontend/FrontendOptions.h"
37676fbe81SDimitry Andric #include "clang/Frontend/FrontendPluginRegistry.h"
3848675466SDimitry Andric #include "clang/Frontend/MigratorOptions.h"
3948675466SDimitry Andric #include "clang/Frontend/PreprocessorOutputOptions.h"
40344a3780SDimitry Andric #include "clang/Frontend/TextDiagnosticBuffer.h"
41bfef3995SDimitry Andric #include "clang/Frontend/Utils.h"
42809500fcSDimitry Andric #include "clang/Lex/HeaderSearchOptions.h"
43bab175ecSDimitry Andric #include "clang/Lex/PreprocessorOptions.h"
4448675466SDimitry Andric #include "clang/Sema/CodeCompleteOptions.h"
45cfca06d7SDimitry Andric #include "clang/Serialization/ASTBitCodes.h"
4645b53394SDimitry Andric #include "clang/Serialization/ModuleFileExtension.h"
4748675466SDimitry Andric #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
4848675466SDimitry Andric #include "llvm/ADT/APInt.h"
4948675466SDimitry Andric #include "llvm/ADT/ArrayRef.h"
5048675466SDimitry Andric #include "llvm/ADT/CachedHashString.h"
51cfca06d7SDimitry Andric #include "llvm/ADT/FloatingPointMode.h"
5213cc256eSDimitry Andric #include "llvm/ADT/Hashing.h"
53344a3780SDimitry Andric #include "llvm/ADT/STLExtras.h"
5448675466SDimitry Andric #include "llvm/ADT/SmallString.h"
5506d4ba38SDimitry Andric #include "llvm/ADT/SmallVector.h"
5648675466SDimitry Andric #include "llvm/ADT/StringRef.h"
571569ce68SRoman Divacky #include "llvm/ADT/StringSwitch.h"
5848675466SDimitry Andric #include "llvm/ADT/Twine.h"
59b60736ecSDimitry Andric #include "llvm/Config/llvm-config.h"
607fa27ce4SDimitry Andric #include "llvm/Frontend/Debug/Options.h"
61676fbe81SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
6245b53394SDimitry Andric #include "llvm/Linker/Linker.h"
6348675466SDimitry Andric #include "llvm/MC/MCTargetOptions.h"
64bfef3995SDimitry Andric #include "llvm/Option/Arg.h"
65bfef3995SDimitry Andric #include "llvm/Option/ArgList.h"
6648675466SDimitry Andric #include "llvm/Option/OptSpecifier.h"
67bfef3995SDimitry Andric #include "llvm/Option/OptTable.h"
68bfef3995SDimitry Andric #include "llvm/Option/Option.h"
692b6b257fSDimitry Andric #include "llvm/ProfileData/InstrProfReader.h"
70b60736ecSDimitry Andric #include "llvm/Remarks/HotnessThresholdParser.h"
719f4dbff6SDimitry Andric #include "llvm/Support/CodeGen.h"
7248675466SDimitry Andric #include "llvm/Support/Compiler.h"
7348675466SDimitry Andric #include "llvm/Support/Error.h"
74b3d5a323SRoman Divacky #include "llvm/Support/ErrorHandling.h"
7548675466SDimitry Andric #include "llvm/Support/ErrorOr.h"
76bfef3995SDimitry Andric #include "llvm/Support/FileSystem.h"
77c0981da4SDimitry Andric #include "llvm/Support/HashBuilder.h"
7848675466SDimitry Andric #include "llvm/Support/MathExtras.h"
7948675466SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
80bca07a45SDimitry Andric #include "llvm/Support/Path.h"
81bfef3995SDimitry Andric #include "llvm/Support/Process.h"
8248675466SDimitry Andric #include "llvm/Support/Regex.h"
8348675466SDimitry Andric #include "llvm/Support/VersionTuple.h"
84676fbe81SDimitry Andric #include "llvm/Support/VirtualFileSystem.h"
8548675466SDimitry Andric #include "llvm/Support/raw_ostream.h"
8645b53394SDimitry Andric #include "llvm/Target/TargetOptions.h"
877fa27ce4SDimitry Andric #include "llvm/TargetParser/Host.h"
887fa27ce4SDimitry Andric #include "llvm/TargetParser/Triple.h"
8948675466SDimitry Andric #include <algorithm>
909f4dbff6SDimitry Andric #include <atomic>
9148675466SDimitry Andric #include <cassert>
9248675466SDimitry Andric #include <cstddef>
9348675466SDimitry Andric #include <cstring>
94e3b55780SDimitry Andric #include <ctime>
95145449b1SDimitry Andric #include <fstream>
96e3b55780SDimitry Andric #include <limits>
979f4dbff6SDimitry Andric #include <memory>
98e3b55780SDimitry Andric #include <optional>
9948675466SDimitry Andric #include <string>
10048675466SDimitry Andric #include <tuple>
101b60736ecSDimitry Andric #include <type_traits>
10248675466SDimitry Andric #include <utility>
10348675466SDimitry Andric #include <vector>
10448675466SDimitry Andric 
105b3d5a323SRoman Divacky using namespace clang;
10648675466SDimitry Andric using namespace driver;
10748675466SDimitry Andric using namespace options;
10848675466SDimitry Andric using namespace llvm::opt;
109b3d5a323SRoman Divacky 
110dbe13110SDimitry Andric //===----------------------------------------------------------------------===//
111145449b1SDimitry Andric // Helpers.
112145449b1SDimitry Andric //===----------------------------------------------------------------------===//
113145449b1SDimitry Andric 
114145449b1SDimitry Andric // Parse misexpect tolerance argument value.
115145449b1SDimitry Andric // Valid option values are integers in the range [0, 100)
parseToleranceOption(StringRef Arg)116e3b55780SDimitry Andric static Expected<std::optional<uint32_t>> parseToleranceOption(StringRef Arg) {
117e3b55780SDimitry Andric   uint32_t Val;
118145449b1SDimitry Andric   if (Arg.getAsInteger(10, Val))
119145449b1SDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
120145449b1SDimitry Andric                                    "Not an integer: %s", Arg.data());
121145449b1SDimitry Andric   return Val;
122145449b1SDimitry Andric }
123145449b1SDimitry Andric 
124145449b1SDimitry Andric //===----------------------------------------------------------------------===//
125dbe13110SDimitry Andric // Initialization.
126dbe13110SDimitry Andric //===----------------------------------------------------------------------===//
127dbe13110SDimitry Andric 
128b1c73532SDimitry Andric namespace {
make_shared_copy(const T & X)129b1c73532SDimitry Andric template <class T> std::shared_ptr<T> make_shared_copy(const T &X) {
130b1c73532SDimitry Andric   return std::make_shared<T>(X);
131b1c73532SDimitry Andric }
132dbe13110SDimitry Andric 
133b1c73532SDimitry Andric template <class T>
makeIntrusiveRefCntCopy(const T & X)134b1c73532SDimitry Andric llvm::IntrusiveRefCntPtr<T> makeIntrusiveRefCntCopy(const T &X) {
135b1c73532SDimitry Andric   return llvm::makeIntrusiveRefCnt<T>(X);
136b1c73532SDimitry Andric }
137b1c73532SDimitry Andric } // namespace
138dbe13110SDimitry Andric 
CompilerInvocationBase()139b1c73532SDimitry Andric CompilerInvocationBase::CompilerInvocationBase()
140b1c73532SDimitry Andric     : LangOpts(std::make_shared<LangOptions>()),
141b1c73532SDimitry Andric       TargetOpts(std::make_shared<TargetOptions>()),
142b1c73532SDimitry Andric       DiagnosticOpts(llvm::makeIntrusiveRefCnt<DiagnosticOptions>()),
143b1c73532SDimitry Andric       HSOpts(std::make_shared<HeaderSearchOptions>()),
144b1c73532SDimitry Andric       PPOpts(std::make_shared<PreprocessorOptions>()),
145b1c73532SDimitry Andric       AnalyzerOpts(llvm::makeIntrusiveRefCnt<AnalyzerOptions>()),
146b1c73532SDimitry Andric       MigratorOpts(std::make_shared<MigratorOptions>()),
147b1c73532SDimitry Andric       APINotesOpts(std::make_shared<APINotesOptions>()),
148b1c73532SDimitry Andric       CodeGenOpts(std::make_shared<CodeGenOptions>()),
149b1c73532SDimitry Andric       FSOpts(std::make_shared<FileSystemOptions>()),
150b1c73532SDimitry Andric       FrontendOpts(std::make_shared<FrontendOptions>()),
151b1c73532SDimitry Andric       DependencyOutputOpts(std::make_shared<DependencyOutputOptions>()),
152b1c73532SDimitry Andric       PreprocessorOutputOpts(std::make_shared<PreprocessorOutputOptions>()) {}
153344a3780SDimitry Andric 
154b1c73532SDimitry Andric CompilerInvocationBase &
deep_copy_assign(const CompilerInvocationBase & X)155b1c73532SDimitry Andric CompilerInvocationBase::deep_copy_assign(const CompilerInvocationBase &X) {
156b1c73532SDimitry Andric   if (this != &X) {
157b1c73532SDimitry Andric     LangOpts = make_shared_copy(X.getLangOpts());
158b1c73532SDimitry Andric     TargetOpts = make_shared_copy(X.getTargetOpts());
159b1c73532SDimitry Andric     DiagnosticOpts = makeIntrusiveRefCntCopy(X.getDiagnosticOpts());
160b1c73532SDimitry Andric     HSOpts = make_shared_copy(X.getHeaderSearchOpts());
161b1c73532SDimitry Andric     PPOpts = make_shared_copy(X.getPreprocessorOpts());
162b1c73532SDimitry Andric     AnalyzerOpts = makeIntrusiveRefCntCopy(X.getAnalyzerOpts());
163b1c73532SDimitry Andric     MigratorOpts = make_shared_copy(X.getMigratorOpts());
164b1c73532SDimitry Andric     APINotesOpts = make_shared_copy(X.getAPINotesOpts());
165b1c73532SDimitry Andric     CodeGenOpts = make_shared_copy(X.getCodeGenOpts());
166b1c73532SDimitry Andric     FSOpts = make_shared_copy(X.getFileSystemOpts());
167b1c73532SDimitry Andric     FrontendOpts = make_shared_copy(X.getFrontendOpts());
168b1c73532SDimitry Andric     DependencyOutputOpts = make_shared_copy(X.getDependencyOutputOpts());
169b1c73532SDimitry Andric     PreprocessorOutputOpts = make_shared_copy(X.getPreprocessorOutputOpts());
170b1c73532SDimitry Andric   }
171344a3780SDimitry Andric   return *this;
172344a3780SDimitry Andric }
173344a3780SDimitry Andric 
174b1c73532SDimitry Andric CompilerInvocationBase &
shallow_copy_assign(const CompilerInvocationBase & X)175b1c73532SDimitry Andric CompilerInvocationBase::shallow_copy_assign(const CompilerInvocationBase &X) {
176b1c73532SDimitry Andric   if (this != &X) {
177b1c73532SDimitry Andric     LangOpts = X.LangOpts;
178b1c73532SDimitry Andric     TargetOpts = X.TargetOpts;
179b1c73532SDimitry Andric     DiagnosticOpts = X.DiagnosticOpts;
180b1c73532SDimitry Andric     HSOpts = X.HSOpts;
181b1c73532SDimitry Andric     PPOpts = X.PPOpts;
182b1c73532SDimitry Andric     AnalyzerOpts = X.AnalyzerOpts;
183b1c73532SDimitry Andric     MigratorOpts = X.MigratorOpts;
184b1c73532SDimitry Andric     APINotesOpts = X.APINotesOpts;
185b1c73532SDimitry Andric     CodeGenOpts = X.CodeGenOpts;
186b1c73532SDimitry Andric     FSOpts = X.FSOpts;
187b1c73532SDimitry Andric     FrontendOpts = X.FrontendOpts;
188b1c73532SDimitry Andric     DependencyOutputOpts = X.DependencyOutputOpts;
189b1c73532SDimitry Andric     PreprocessorOutputOpts = X.PreprocessorOutputOpts;
190b1c73532SDimitry Andric   }
191b1c73532SDimitry Andric   return *this;
192b1c73532SDimitry Andric }
193344a3780SDimitry Andric 
CompilerInvocation(const CowCompilerInvocation & X)194ac9a064cSDimitry Andric CompilerInvocation::CompilerInvocation(const CowCompilerInvocation &X)
195ac9a064cSDimitry Andric     : CompilerInvocationBase(EmptyConstructor{}) {
196ac9a064cSDimitry Andric   CompilerInvocationBase::deep_copy_assign(X);
197ac9a064cSDimitry Andric }
198ac9a064cSDimitry Andric 
199ac9a064cSDimitry Andric CompilerInvocation &
operator =(const CowCompilerInvocation & X)200ac9a064cSDimitry Andric CompilerInvocation::operator=(const CowCompilerInvocation &X) {
201ac9a064cSDimitry Andric   CompilerInvocationBase::deep_copy_assign(X);
202ac9a064cSDimitry Andric   return *this;
203ac9a064cSDimitry Andric }
204ac9a064cSDimitry Andric 
205b1c73532SDimitry Andric namespace {
206b1c73532SDimitry Andric template <typename T>
ensureOwned(std::shared_ptr<T> & Storage)207b1c73532SDimitry Andric T &ensureOwned(std::shared_ptr<T> &Storage) {
208b1c73532SDimitry Andric   if (Storage.use_count() > 1)
209b1c73532SDimitry Andric     Storage = std::make_shared<T>(*Storage);
210b1c73532SDimitry Andric   return *Storage;
211b1c73532SDimitry Andric }
212b1c73532SDimitry Andric 
213b1c73532SDimitry Andric template <typename T>
ensureOwned(llvm::IntrusiveRefCntPtr<T> & Storage)214b1c73532SDimitry Andric T &ensureOwned(llvm::IntrusiveRefCntPtr<T> &Storage) {
215b1c73532SDimitry Andric   if (Storage.useCount() > 1)
216b1c73532SDimitry Andric     Storage = llvm::makeIntrusiveRefCnt<T>(*Storage);
217b1c73532SDimitry Andric   return *Storage;
218b1c73532SDimitry Andric }
219b1c73532SDimitry Andric } // namespace
220b1c73532SDimitry Andric 
getMutLangOpts()221b1c73532SDimitry Andric LangOptions &CowCompilerInvocation::getMutLangOpts() {
222b1c73532SDimitry Andric   return ensureOwned(LangOpts);
223b1c73532SDimitry Andric }
224b1c73532SDimitry Andric 
getMutTargetOpts()225b1c73532SDimitry Andric TargetOptions &CowCompilerInvocation::getMutTargetOpts() {
226b1c73532SDimitry Andric   return ensureOwned(TargetOpts);
227b1c73532SDimitry Andric }
228b1c73532SDimitry Andric 
getMutDiagnosticOpts()229b1c73532SDimitry Andric DiagnosticOptions &CowCompilerInvocation::getMutDiagnosticOpts() {
230b1c73532SDimitry Andric   return ensureOwned(DiagnosticOpts);
231b1c73532SDimitry Andric }
232b1c73532SDimitry Andric 
getMutHeaderSearchOpts()233b1c73532SDimitry Andric HeaderSearchOptions &CowCompilerInvocation::getMutHeaderSearchOpts() {
234b1c73532SDimitry Andric   return ensureOwned(HSOpts);
235b1c73532SDimitry Andric }
236b1c73532SDimitry Andric 
getMutPreprocessorOpts()237b1c73532SDimitry Andric PreprocessorOptions &CowCompilerInvocation::getMutPreprocessorOpts() {
238b1c73532SDimitry Andric   return ensureOwned(PPOpts);
239b1c73532SDimitry Andric }
240b1c73532SDimitry Andric 
getMutAnalyzerOpts()241b1c73532SDimitry Andric AnalyzerOptions &CowCompilerInvocation::getMutAnalyzerOpts() {
242b1c73532SDimitry Andric   return ensureOwned(AnalyzerOpts);
243b1c73532SDimitry Andric }
244b1c73532SDimitry Andric 
getMutMigratorOpts()245b1c73532SDimitry Andric MigratorOptions &CowCompilerInvocation::getMutMigratorOpts() {
246b1c73532SDimitry Andric   return ensureOwned(MigratorOpts);
247b1c73532SDimitry Andric }
248b1c73532SDimitry Andric 
getMutAPINotesOpts()249b1c73532SDimitry Andric APINotesOptions &CowCompilerInvocation::getMutAPINotesOpts() {
250b1c73532SDimitry Andric   return ensureOwned(APINotesOpts);
251b1c73532SDimitry Andric }
252b1c73532SDimitry Andric 
getMutCodeGenOpts()253b1c73532SDimitry Andric CodeGenOptions &CowCompilerInvocation::getMutCodeGenOpts() {
254b1c73532SDimitry Andric   return ensureOwned(CodeGenOpts);
255b1c73532SDimitry Andric }
256b1c73532SDimitry Andric 
getMutFileSystemOpts()257b1c73532SDimitry Andric FileSystemOptions &CowCompilerInvocation::getMutFileSystemOpts() {
258b1c73532SDimitry Andric   return ensureOwned(FSOpts);
259b1c73532SDimitry Andric }
260b1c73532SDimitry Andric 
getMutFrontendOpts()261b1c73532SDimitry Andric FrontendOptions &CowCompilerInvocation::getMutFrontendOpts() {
262b1c73532SDimitry Andric   return ensureOwned(FrontendOpts);
263b1c73532SDimitry Andric }
264b1c73532SDimitry Andric 
getMutDependencyOutputOpts()265b1c73532SDimitry Andric DependencyOutputOptions &CowCompilerInvocation::getMutDependencyOutputOpts() {
266b1c73532SDimitry Andric   return ensureOwned(DependencyOutputOpts);
267b1c73532SDimitry Andric }
268b1c73532SDimitry Andric 
269b1c73532SDimitry Andric PreprocessorOutputOptions &
getMutPreprocessorOutputOpts()270b1c73532SDimitry Andric CowCompilerInvocation::getMutPreprocessorOutputOpts() {
271b1c73532SDimitry Andric   return ensureOwned(PreprocessorOutputOpts);
272b1c73532SDimitry Andric }
2739f4dbff6SDimitry Andric 
274dbe13110SDimitry Andric //===----------------------------------------------------------------------===//
275cfca06d7SDimitry Andric // Normalizers
276cfca06d7SDimitry Andric //===----------------------------------------------------------------------===//
277cfca06d7SDimitry Andric 
278b1c73532SDimitry Andric using ArgumentConsumer = CompilerInvocation::ArgumentConsumer;
279b1c73532SDimitry Andric 
280cfca06d7SDimitry Andric #define SIMPLE_ENUM_VALUE_TABLE
281cfca06d7SDimitry Andric #include "clang/Driver/Options.inc"
282cfca06d7SDimitry Andric #undef SIMPLE_ENUM_VALUE_TABLE
283cfca06d7SDimitry Andric 
normalizeSimpleFlag(OptSpecifier Opt,unsigned TableIndex,const ArgList & Args,DiagnosticsEngine & Diags)284e3b55780SDimitry Andric static std::optional<bool> normalizeSimpleFlag(OptSpecifier Opt,
285344a3780SDimitry Andric                                                unsigned TableIndex,
286344a3780SDimitry Andric                                                const ArgList &Args,
287344a3780SDimitry Andric                                                DiagnosticsEngine &Diags) {
288b60736ecSDimitry Andric   if (Args.hasArg(Opt))
289b60736ecSDimitry Andric     return true;
290e3b55780SDimitry Andric   return std::nullopt;
291b60736ecSDimitry Andric }
292b60736ecSDimitry Andric 
normalizeSimpleNegativeFlag(OptSpecifier Opt,unsigned,const ArgList & Args,DiagnosticsEngine &)293e3b55780SDimitry Andric static std::optional<bool> normalizeSimpleNegativeFlag(OptSpecifier Opt,
294e3b55780SDimitry Andric                                                        unsigned,
295cfca06d7SDimitry Andric                                                        const ArgList &Args,
296344a3780SDimitry Andric                                                        DiagnosticsEngine &) {
297b60736ecSDimitry Andric   if (Args.hasArg(Opt))
298b60736ecSDimitry Andric     return false;
299e3b55780SDimitry Andric   return std::nullopt;
300b60736ecSDimitry Andric }
301b60736ecSDimitry Andric 
302b60736ecSDimitry Andric /// The tblgen-erated code passes in a fifth parameter of an arbitrary type, but
303b60736ecSDimitry Andric /// denormalizeSimpleFlags never looks at it. Avoid bloating compile-time with
304b60736ecSDimitry Andric /// unnecessary template instantiations and just ignore it with a variadic
305b60736ecSDimitry Andric /// argument.
denormalizeSimpleFlag(ArgumentConsumer Consumer,const Twine & Spelling,Option::OptionClass,unsigned,...)306b1c73532SDimitry Andric static void denormalizeSimpleFlag(ArgumentConsumer Consumer,
307b1c73532SDimitry Andric                                   const Twine &Spelling, Option::OptionClass,
308b1c73532SDimitry Andric                                   unsigned, /*T*/...) {
309b1c73532SDimitry Andric   Consumer(Spelling);
310b60736ecSDimitry Andric }
311b60736ecSDimitry Andric 
is_uint64_t_convertible()312b60736ecSDimitry Andric template <typename T> static constexpr bool is_uint64_t_convertible() {
313e3b55780SDimitry Andric   return !std::is_same_v<T, uint64_t> && llvm::is_integral_or_enum<T>::value;
314b60736ecSDimitry Andric }
315b60736ecSDimitry Andric 
316b60736ecSDimitry Andric template <typename T,
317b60736ecSDimitry Andric           std::enable_if_t<!is_uint64_t_convertible<T>(), bool> = false>
makeFlagToValueNormalizer(T Value)318b60736ecSDimitry Andric static auto makeFlagToValueNormalizer(T Value) {
319b60736ecSDimitry Andric   return [Value](OptSpecifier Opt, unsigned, const ArgList &Args,
320e3b55780SDimitry Andric                  DiagnosticsEngine &) -> std::optional<T> {
321b60736ecSDimitry Andric     if (Args.hasArg(Opt))
322b60736ecSDimitry Andric       return Value;
323e3b55780SDimitry Andric     return std::nullopt;
324b60736ecSDimitry Andric   };
325b60736ecSDimitry Andric }
326b60736ecSDimitry Andric 
327b60736ecSDimitry Andric template <typename T,
328b60736ecSDimitry Andric           std::enable_if_t<is_uint64_t_convertible<T>(), bool> = false>
makeFlagToValueNormalizer(T Value)329b60736ecSDimitry Andric static auto makeFlagToValueNormalizer(T Value) {
330b60736ecSDimitry Andric   return makeFlagToValueNormalizer(uint64_t(Value));
331b60736ecSDimitry Andric }
332b60736ecSDimitry Andric 
makeBooleanOptionNormalizer(bool Value,bool OtherValue,OptSpecifier OtherOpt)333b60736ecSDimitry Andric static auto makeBooleanOptionNormalizer(bool Value, bool OtherValue,
334b60736ecSDimitry Andric                                         OptSpecifier OtherOpt) {
335e3b55780SDimitry Andric   return [Value, OtherValue,
336e3b55780SDimitry Andric           OtherOpt](OptSpecifier Opt, unsigned, const ArgList &Args,
337e3b55780SDimitry Andric                     DiagnosticsEngine &) -> std::optional<bool> {
338b60736ecSDimitry Andric     if (const Arg *A = Args.getLastArg(Opt, OtherOpt)) {
339b60736ecSDimitry Andric       return A->getOption().matches(Opt) ? Value : OtherValue;
340b60736ecSDimitry Andric     }
341e3b55780SDimitry Andric     return std::nullopt;
342b60736ecSDimitry Andric   };
343b60736ecSDimitry Andric }
344b60736ecSDimitry Andric 
makeBooleanOptionDenormalizer(bool Value)345b60736ecSDimitry Andric static auto makeBooleanOptionDenormalizer(bool Value) {
346b1c73532SDimitry Andric   return [Value](ArgumentConsumer Consumer, const Twine &Spelling,
347b1c73532SDimitry Andric                  Option::OptionClass, unsigned, bool KeyPath) {
348b60736ecSDimitry Andric     if (KeyPath == Value)
349b1c73532SDimitry Andric       Consumer(Spelling);
350b60736ecSDimitry Andric   };
351b60736ecSDimitry Andric }
352b60736ecSDimitry Andric 
denormalizeStringImpl(ArgumentConsumer Consumer,const Twine & Spelling,Option::OptionClass OptClass,unsigned,const Twine & Value)353b1c73532SDimitry Andric static void denormalizeStringImpl(ArgumentConsumer Consumer,
354b1c73532SDimitry Andric                                   const Twine &Spelling,
355b60736ecSDimitry Andric                                   Option::OptionClass OptClass, unsigned,
356344a3780SDimitry Andric                                   const Twine &Value) {
357b60736ecSDimitry Andric   switch (OptClass) {
358b60736ecSDimitry Andric   case Option::SeparateClass:
359b60736ecSDimitry Andric   case Option::JoinedOrSeparateClass:
360344a3780SDimitry Andric   case Option::JoinedAndSeparateClass:
361b1c73532SDimitry Andric     Consumer(Spelling);
362b1c73532SDimitry Andric     Consumer(Value);
363b60736ecSDimitry Andric     break;
364b60736ecSDimitry Andric   case Option::JoinedClass:
365344a3780SDimitry Andric   case Option::CommaJoinedClass:
366b1c73532SDimitry Andric     Consumer(Spelling + Value);
367b60736ecSDimitry Andric     break;
368b60736ecSDimitry Andric   default:
369b60736ecSDimitry Andric     llvm_unreachable("Cannot denormalize an option with option class "
370b60736ecSDimitry Andric                      "incompatible with string denormalization.");
371b60736ecSDimitry Andric   }
372b60736ecSDimitry Andric }
373b60736ecSDimitry Andric 
374b60736ecSDimitry Andric template <typename T>
denormalizeString(ArgumentConsumer Consumer,const Twine & Spelling,Option::OptionClass OptClass,unsigned TableIndex,T Value)375b1c73532SDimitry Andric static void denormalizeString(ArgumentConsumer Consumer, const Twine &Spelling,
376b1c73532SDimitry Andric                               Option::OptionClass OptClass, unsigned TableIndex,
377b1c73532SDimitry Andric                               T Value) {
378b1c73532SDimitry Andric   denormalizeStringImpl(Consumer, Spelling, OptClass, TableIndex, Twine(Value));
379b60736ecSDimitry Andric }
380b60736ecSDimitry Andric 
381e3b55780SDimitry Andric static std::optional<SimpleEnumValue>
findValueTableByName(const SimpleEnumValueTable & Table,StringRef Name)382b60736ecSDimitry Andric findValueTableByName(const SimpleEnumValueTable &Table, StringRef Name) {
383b60736ecSDimitry Andric   for (int I = 0, E = Table.Size; I != E; ++I)
384b60736ecSDimitry Andric     if (Name == Table.Table[I].Name)
385b60736ecSDimitry Andric       return Table.Table[I];
386b60736ecSDimitry Andric 
387e3b55780SDimitry Andric   return std::nullopt;
388b60736ecSDimitry Andric }
389b60736ecSDimitry Andric 
390e3b55780SDimitry Andric static std::optional<SimpleEnumValue>
findValueTableByValue(const SimpleEnumValueTable & Table,unsigned Value)391b60736ecSDimitry Andric findValueTableByValue(const SimpleEnumValueTable &Table, unsigned Value) {
392b60736ecSDimitry Andric   for (int I = 0, E = Table.Size; I != E; ++I)
393b60736ecSDimitry Andric     if (Value == Table.Table[I].Value)
394b60736ecSDimitry Andric       return Table.Table[I];
395b60736ecSDimitry Andric 
396e3b55780SDimitry Andric   return std::nullopt;
397b60736ecSDimitry Andric }
398b60736ecSDimitry Andric 
normalizeSimpleEnum(OptSpecifier Opt,unsigned TableIndex,const ArgList & Args,DiagnosticsEngine & Diags)399e3b55780SDimitry Andric static std::optional<unsigned> normalizeSimpleEnum(OptSpecifier Opt,
400344a3780SDimitry Andric                                                    unsigned TableIndex,
401344a3780SDimitry Andric                                                    const ArgList &Args,
402344a3780SDimitry Andric                                                    DiagnosticsEngine &Diags) {
403cfca06d7SDimitry Andric   assert(TableIndex < SimpleEnumValueTablesSize);
404cfca06d7SDimitry Andric   const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex];
405cfca06d7SDimitry Andric 
406cfca06d7SDimitry Andric   auto *Arg = Args.getLastArg(Opt);
407cfca06d7SDimitry Andric   if (!Arg)
408e3b55780SDimitry Andric     return std::nullopt;
409cfca06d7SDimitry Andric 
410cfca06d7SDimitry Andric   StringRef ArgValue = Arg->getValue();
411b60736ecSDimitry Andric   if (auto MaybeEnumVal = findValueTableByName(Table, ArgValue))
412b60736ecSDimitry Andric     return MaybeEnumVal->Value;
413cfca06d7SDimitry Andric 
414cfca06d7SDimitry Andric   Diags.Report(diag::err_drv_invalid_value)
415cfca06d7SDimitry Andric       << Arg->getAsString(Args) << ArgValue;
416e3b55780SDimitry Andric   return std::nullopt;
417cfca06d7SDimitry Andric }
418cfca06d7SDimitry Andric 
denormalizeSimpleEnumImpl(ArgumentConsumer Consumer,const Twine & Spelling,Option::OptionClass OptClass,unsigned TableIndex,unsigned Value)419b1c73532SDimitry Andric static void denormalizeSimpleEnumImpl(ArgumentConsumer Consumer,
420b1c73532SDimitry Andric                                       const Twine &Spelling,
421b60736ecSDimitry Andric                                       Option::OptionClass OptClass,
422cfca06d7SDimitry Andric                                       unsigned TableIndex, unsigned Value) {
423cfca06d7SDimitry Andric   assert(TableIndex < SimpleEnumValueTablesSize);
424cfca06d7SDimitry Andric   const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex];
425b60736ecSDimitry Andric   if (auto MaybeEnumVal = findValueTableByValue(Table, Value)) {
426b1c73532SDimitry Andric     denormalizeString(Consumer, Spelling, OptClass, TableIndex,
427b60736ecSDimitry Andric                       MaybeEnumVal->Name);
428b60736ecSDimitry Andric   } else {
429cfca06d7SDimitry Andric     llvm_unreachable("The simple enum value was not correctly defined in "
430cfca06d7SDimitry Andric                      "the tablegen option description");
431cfca06d7SDimitry Andric   }
432b60736ecSDimitry Andric }
433cfca06d7SDimitry Andric 
434b60736ecSDimitry Andric template <typename T>
denormalizeSimpleEnum(ArgumentConsumer Consumer,const Twine & Spelling,Option::OptionClass OptClass,unsigned TableIndex,T Value)435b1c73532SDimitry Andric static void denormalizeSimpleEnum(ArgumentConsumer Consumer,
436b1c73532SDimitry Andric                                   const Twine &Spelling,
437b60736ecSDimitry Andric                                   Option::OptionClass OptClass,
438b60736ecSDimitry Andric                                   unsigned TableIndex, T Value) {
439b1c73532SDimitry Andric   return denormalizeSimpleEnumImpl(Consumer, Spelling, OptClass, TableIndex,
440b60736ecSDimitry Andric                                    static_cast<unsigned>(Value));
441b60736ecSDimitry Andric }
442b60736ecSDimitry Andric 
normalizeString(OptSpecifier Opt,int TableIndex,const ArgList & Args,DiagnosticsEngine & Diags)443e3b55780SDimitry Andric static std::optional<std::string> normalizeString(OptSpecifier Opt,
444e3b55780SDimitry Andric                                                   int TableIndex,
445b60736ecSDimitry Andric                                                   const ArgList &Args,
446344a3780SDimitry Andric                                                   DiagnosticsEngine &Diags) {
447b60736ecSDimitry Andric   auto *Arg = Args.getLastArg(Opt);
448b60736ecSDimitry Andric   if (!Arg)
449e3b55780SDimitry Andric     return std::nullopt;
450b60736ecSDimitry Andric   return std::string(Arg->getValue());
451b60736ecSDimitry Andric }
452b60736ecSDimitry Andric 
453b60736ecSDimitry Andric template <typename IntTy>
normalizeStringIntegral(OptSpecifier Opt,int,const ArgList & Args,DiagnosticsEngine & Diags)454e3b55780SDimitry Andric static std::optional<IntTy> normalizeStringIntegral(OptSpecifier Opt, int,
455344a3780SDimitry Andric                                                     const ArgList &Args,
456344a3780SDimitry Andric                                                     DiagnosticsEngine &Diags) {
457b60736ecSDimitry Andric   auto *Arg = Args.getLastArg(Opt);
458b60736ecSDimitry Andric   if (!Arg)
459e3b55780SDimitry Andric     return std::nullopt;
460b60736ecSDimitry Andric   IntTy Res;
461b60736ecSDimitry Andric   if (StringRef(Arg->getValue()).getAsInteger(0, Res)) {
462b60736ecSDimitry Andric     Diags.Report(diag::err_drv_invalid_int_value)
463b60736ecSDimitry Andric         << Arg->getAsString(Args) << Arg->getValue();
464e3b55780SDimitry Andric     return std::nullopt;
465b60736ecSDimitry Andric   }
466b60736ecSDimitry Andric   return Res;
467b60736ecSDimitry Andric }
468b60736ecSDimitry Andric 
469e3b55780SDimitry Andric static std::optional<std::vector<std::string>>
normalizeStringVector(OptSpecifier Opt,int,const ArgList & Args,DiagnosticsEngine &)470b60736ecSDimitry Andric normalizeStringVector(OptSpecifier Opt, int, const ArgList &Args,
471344a3780SDimitry Andric                       DiagnosticsEngine &) {
472b60736ecSDimitry Andric   return Args.getAllArgValues(Opt);
473b60736ecSDimitry Andric }
474b60736ecSDimitry Andric 
denormalizeStringVector(ArgumentConsumer Consumer,const Twine & Spelling,Option::OptionClass OptClass,unsigned TableIndex,const std::vector<std::string> & Values)475b1c73532SDimitry Andric static void denormalizeStringVector(ArgumentConsumer Consumer,
476b1c73532SDimitry Andric                                     const Twine &Spelling,
477b60736ecSDimitry Andric                                     Option::OptionClass OptClass,
478cfca06d7SDimitry Andric                                     unsigned TableIndex,
479b60736ecSDimitry Andric                                     const std::vector<std::string> &Values) {
480b60736ecSDimitry Andric   switch (OptClass) {
481b60736ecSDimitry Andric   case Option::CommaJoinedClass: {
482b60736ecSDimitry Andric     std::string CommaJoinedValue;
483b60736ecSDimitry Andric     if (!Values.empty()) {
484b60736ecSDimitry Andric       CommaJoinedValue.append(Values.front());
485b60736ecSDimitry Andric       for (const std::string &Value : llvm::drop_begin(Values, 1)) {
486b60736ecSDimitry Andric         CommaJoinedValue.append(",");
487b60736ecSDimitry Andric         CommaJoinedValue.append(Value);
488b60736ecSDimitry Andric       }
489b60736ecSDimitry Andric     }
490b1c73532SDimitry Andric     denormalizeString(Consumer, Spelling, Option::OptionClass::JoinedClass,
491b60736ecSDimitry Andric                       TableIndex, CommaJoinedValue);
492b60736ecSDimitry Andric     break;
493b60736ecSDimitry Andric   }
494b60736ecSDimitry Andric   case Option::JoinedClass:
495b60736ecSDimitry Andric   case Option::SeparateClass:
496b60736ecSDimitry Andric   case Option::JoinedOrSeparateClass:
497b60736ecSDimitry Andric     for (const std::string &Value : Values)
498b1c73532SDimitry Andric       denormalizeString(Consumer, Spelling, OptClass, TableIndex, Value);
499b60736ecSDimitry Andric     break;
500b60736ecSDimitry Andric   default:
501b60736ecSDimitry Andric     llvm_unreachable("Cannot denormalize an option with option class "
502b60736ecSDimitry Andric                      "incompatible with string vector denormalization.");
503b60736ecSDimitry Andric   }
504cfca06d7SDimitry Andric }
505cfca06d7SDimitry Andric 
normalizeTriple(OptSpecifier Opt,int TableIndex,const ArgList & Args,DiagnosticsEngine & Diags)506e3b55780SDimitry Andric static std::optional<std::string> normalizeTriple(OptSpecifier Opt,
507e3b55780SDimitry Andric                                                   int TableIndex,
508cfca06d7SDimitry Andric                                                   const ArgList &Args,
509344a3780SDimitry Andric                                                   DiagnosticsEngine &Diags) {
510cfca06d7SDimitry Andric   auto *Arg = Args.getLastArg(Opt);
511cfca06d7SDimitry Andric   if (!Arg)
512e3b55780SDimitry Andric     return std::nullopt;
513cfca06d7SDimitry Andric   return llvm::Triple::normalize(Arg->getValue());
514cfca06d7SDimitry Andric }
515cfca06d7SDimitry Andric 
516b60736ecSDimitry Andric template <typename T, typename U>
mergeForwardValue(T KeyPath,U Value)517b60736ecSDimitry Andric static T mergeForwardValue(T KeyPath, U Value) {
518b60736ecSDimitry Andric   return static_cast<T>(Value);
519b60736ecSDimitry Andric }
520b60736ecSDimitry Andric 
mergeMaskValue(T KeyPath,U Value)521b60736ecSDimitry Andric template <typename T, typename U> static T mergeMaskValue(T KeyPath, U Value) {
522b60736ecSDimitry Andric   return KeyPath | Value;
523b60736ecSDimitry Andric }
524b60736ecSDimitry Andric 
extractForwardValue(T KeyPath)525b60736ecSDimitry Andric template <typename T> static T extractForwardValue(T KeyPath) {
526b60736ecSDimitry Andric   return KeyPath;
527b60736ecSDimitry Andric }
528b60736ecSDimitry Andric 
529b60736ecSDimitry Andric template <typename T, typename U, U Value>
extractMaskValue(T KeyPath)530b60736ecSDimitry Andric static T extractMaskValue(T KeyPath) {
531344a3780SDimitry Andric   return ((KeyPath & Value) == Value) ? static_cast<T>(Value) : T();
532b60736ecSDimitry Andric }
533b60736ecSDimitry Andric 
534344a3780SDimitry Andric #define PARSE_OPTION_WITH_MARSHALLING(                                         \
535b1c73532SDimitry Andric     ARGS, DIAGS, PREFIX_TYPE, SPELLING, ID, KIND, GROUP, ALIAS, ALIASARGS,     \
536ac9a064cSDimitry Andric     FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES, \
537ac9a064cSDimitry Andric     SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK,          \
538ac9a064cSDimitry Andric     IMPLIED_VALUE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX)   \
539b1c73532SDimitry Andric   if ((VISIBILITY) & options::CC1Option) {                                     \
540b60736ecSDimitry Andric     KEYPATH = MERGER(KEYPATH, DEFAULT_VALUE);                                  \
541b60736ecSDimitry Andric     if (IMPLIED_CHECK)                                                         \
542b60736ecSDimitry Andric       KEYPATH = MERGER(KEYPATH, IMPLIED_VALUE);                                \
543b60736ecSDimitry Andric     if (SHOULD_PARSE)                                                          \
544344a3780SDimitry Andric       if (auto MaybeValue = NORMALIZER(OPT_##ID, TABLE_INDEX, ARGS, DIAGS))    \
545b60736ecSDimitry Andric         KEYPATH =                                                              \
546b60736ecSDimitry Andric             MERGER(KEYPATH, static_cast<decltype(KEYPATH)>(*MaybeValue));      \
547b60736ecSDimitry Andric   }
548b60736ecSDimitry Andric 
549344a3780SDimitry Andric // Capture the extracted value as a lambda argument to avoid potential issues
550344a3780SDimitry Andric // with lifetime extension of the reference.
551344a3780SDimitry Andric #define GENERATE_OPTION_WITH_MARSHALLING(                                      \
552b1c73532SDimitry Andric     CONSUMER, PREFIX_TYPE, SPELLING, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, \
553ac9a064cSDimitry Andric     VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES,        \
554ac9a064cSDimitry Andric     SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK,          \
555ac9a064cSDimitry Andric     IMPLIED_VALUE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX)   \
556b1c73532SDimitry Andric   if ((VISIBILITY) & options::CC1Option) {                                     \
557344a3780SDimitry Andric     [&](const auto &Extracted) {                                               \
558344a3780SDimitry Andric       if (ALWAYS_EMIT ||                                                       \
559344a3780SDimitry Andric           (Extracted !=                                                        \
560344a3780SDimitry Andric            static_cast<decltype(KEYPATH)>((IMPLIED_CHECK) ? (IMPLIED_VALUE)    \
561344a3780SDimitry Andric                                                           : (DEFAULT_VALUE)))) \
562b1c73532SDimitry Andric         DENORMALIZER(CONSUMER, SPELLING, Option::KIND##Class, TABLE_INDEX,     \
563b1c73532SDimitry Andric                      Extracted);                                               \
564344a3780SDimitry Andric     }(EXTRACTOR(KEYPATH));                                                     \
565344a3780SDimitry Andric   }
566344a3780SDimitry Andric 
5676f8fc217SDimitry Andric static StringRef GetInputKindName(InputKind IK);
568b60736ecSDimitry Andric 
FixupInvocation(CompilerInvocation & Invocation,DiagnosticsEngine & Diags,const ArgList & Args,InputKind IK)569344a3780SDimitry Andric static bool FixupInvocation(CompilerInvocation &Invocation,
570344a3780SDimitry Andric                             DiagnosticsEngine &Diags, const ArgList &Args,
571b60736ecSDimitry Andric                             InputKind IK) {
572344a3780SDimitry Andric   unsigned NumErrorsBefore = Diags.getNumErrors();
573344a3780SDimitry Andric 
574b1c73532SDimitry Andric   LangOptions &LangOpts = Invocation.getLangOpts();
575b60736ecSDimitry Andric   CodeGenOptions &CodeGenOpts = Invocation.getCodeGenOpts();
576b60736ecSDimitry Andric   TargetOptions &TargetOpts = Invocation.getTargetOpts();
577b60736ecSDimitry Andric   FrontendOptions &FrontendOpts = Invocation.getFrontendOpts();
578b60736ecSDimitry Andric   CodeGenOpts.XRayInstrumentFunctions = LangOpts.XRayInstrument;
579b60736ecSDimitry Andric   CodeGenOpts.XRayAlwaysEmitCustomEvents = LangOpts.XRayAlwaysEmitCustomEvents;
580b60736ecSDimitry Andric   CodeGenOpts.XRayAlwaysEmitTypedEvents = LangOpts.XRayAlwaysEmitTypedEvents;
581b60736ecSDimitry Andric   CodeGenOpts.DisableFree = FrontendOpts.DisableFree;
582b60736ecSDimitry Andric   FrontendOpts.GenerateGlobalModuleIndex = FrontendOpts.UseGlobalModuleIndex;
583c0981da4SDimitry Andric   if (FrontendOpts.ShowStats)
584c0981da4SDimitry Andric     CodeGenOpts.ClearASTBeforeBackend = false;
585344a3780SDimitry Andric   LangOpts.SanitizeCoverage = CodeGenOpts.hasSanitizeCoverage();
586b60736ecSDimitry Andric   LangOpts.ForceEmitVTables = CodeGenOpts.ForceEmitVTables;
587b60736ecSDimitry Andric   LangOpts.SpeculativeLoadHardening = CodeGenOpts.SpeculativeLoadHardening;
588b60736ecSDimitry Andric   LangOpts.CurrentModule = LangOpts.ModuleName;
589b60736ecSDimitry Andric 
590b60736ecSDimitry Andric   llvm::Triple T(TargetOpts.Triple);
591b60736ecSDimitry Andric   llvm::Triple::ArchType Arch = T.getArch();
592b60736ecSDimitry Andric 
593b60736ecSDimitry Andric   CodeGenOpts.CodeModel = TargetOpts.CodeModel;
594b1c73532SDimitry Andric   CodeGenOpts.LargeDataThreshold = TargetOpts.LargeDataThreshold;
595b60736ecSDimitry Andric 
596344a3780SDimitry Andric   if (LangOpts.getExceptionHandling() !=
597344a3780SDimitry Andric           LangOptions::ExceptionHandlingKind::None &&
598b60736ecSDimitry Andric       T.isWindowsMSVCEnvironment())
599b60736ecSDimitry Andric     Diags.Report(diag::err_fe_invalid_exception_model)
600b60736ecSDimitry Andric         << static_cast<unsigned>(LangOpts.getExceptionHandling()) << T.str();
601b60736ecSDimitry Andric 
602b60736ecSDimitry Andric   if (LangOpts.AppleKext && !LangOpts.CPlusPlus)
603b60736ecSDimitry Andric     Diags.Report(diag::warn_c_kext);
604b60736ecSDimitry Andric 
605b60736ecSDimitry Andric   if (LangOpts.NewAlignOverride &&
606b60736ecSDimitry Andric       !llvm::isPowerOf2_32(LangOpts.NewAlignOverride)) {
607b60736ecSDimitry Andric     Arg *A = Args.getLastArg(OPT_fnew_alignment_EQ);
608b60736ecSDimitry Andric     Diags.Report(diag::err_fe_invalid_alignment)
609b60736ecSDimitry Andric         << A->getAsString(Args) << A->getValue();
610b60736ecSDimitry Andric     LangOpts.NewAlignOverride = 0;
611b60736ecSDimitry Andric   }
612b60736ecSDimitry Andric 
613ac9a064cSDimitry Andric   // The -f[no-]raw-string-literals option is only valid in C and in C++
614ac9a064cSDimitry Andric   // standards before C++11.
615ac9a064cSDimitry Andric   if (LangOpts.CPlusPlus11) {
616ac9a064cSDimitry Andric     if (Args.hasArg(OPT_fraw_string_literals, OPT_fno_raw_string_literals)) {
617ac9a064cSDimitry Andric       Args.claimAllArgs(OPT_fraw_string_literals, OPT_fno_raw_string_literals);
618ac9a064cSDimitry Andric       Diags.Report(diag::warn_drv_fraw_string_literals_in_cxx11)
619ac9a064cSDimitry Andric           << bool(LangOpts.RawStringLiterals);
620ac9a064cSDimitry Andric     }
621ac9a064cSDimitry Andric 
622ac9a064cSDimitry Andric     // Do not allow disabling raw string literals in C++11 or later.
623ac9a064cSDimitry Andric     LangOpts.RawStringLiterals = true;
624ac9a064cSDimitry Andric   }
625ac9a064cSDimitry Andric 
626344a3780SDimitry Andric   // Prevent the user from specifying both -fsycl-is-device and -fsycl-is-host.
627344a3780SDimitry Andric   if (LangOpts.SYCLIsDevice && LangOpts.SYCLIsHost)
628344a3780SDimitry Andric     Diags.Report(diag::err_drv_argument_not_allowed_with) << "-fsycl-is-device"
629344a3780SDimitry Andric                                                           << "-fsycl-is-host";
630344a3780SDimitry Andric 
631b60736ecSDimitry Andric   if (Args.hasArg(OPT_fgnu89_inline) && LangOpts.CPlusPlus)
632b60736ecSDimitry Andric     Diags.Report(diag::err_drv_argument_not_allowed_with)
633b60736ecSDimitry Andric         << "-fgnu89-inline" << GetInputKindName(IK);
634b60736ecSDimitry Andric 
635e3b55780SDimitry Andric   if (Args.hasArg(OPT_hlsl_entrypoint) && !LangOpts.HLSL)
636e3b55780SDimitry Andric     Diags.Report(diag::err_drv_argument_not_allowed_with)
637e3b55780SDimitry Andric         << "-hlsl-entry" << GetInputKindName(IK);
638e3b55780SDimitry Andric 
639b60736ecSDimitry Andric   if (Args.hasArg(OPT_fgpu_allow_device_init) && !LangOpts.HIP)
640b60736ecSDimitry Andric     Diags.Report(diag::warn_ignored_hip_only_option)
641b60736ecSDimitry Andric         << Args.getLastArg(OPT_fgpu_allow_device_init)->getAsString(Args);
642b60736ecSDimitry Andric 
643b60736ecSDimitry Andric   if (Args.hasArg(OPT_gpu_max_threads_per_block_EQ) && !LangOpts.HIP)
644b60736ecSDimitry Andric     Diags.Report(diag::warn_ignored_hip_only_option)
645b60736ecSDimitry Andric         << Args.getLastArg(OPT_gpu_max_threads_per_block_EQ)->getAsString(Args);
646b60736ecSDimitry Andric 
647145449b1SDimitry Andric   // When these options are used, the compiler is allowed to apply
648145449b1SDimitry Andric   // optimizations that may affect the final result. For example
649145449b1SDimitry Andric   // (x+y)+z is transformed to x+(y+z) but may not give the same
650145449b1SDimitry Andric   // final result; it's not value safe.
651145449b1SDimitry Andric   // Another example can be to simplify x/x to 1.0 but x could be 0.0, INF
652145449b1SDimitry Andric   // or NaN. Final result may then differ. An error is issued when the eval
653145449b1SDimitry Andric   // method is set with one of these options.
654145449b1SDimitry Andric   if (Args.hasArg(OPT_ffp_eval_method_EQ)) {
655145449b1SDimitry Andric     if (LangOpts.ApproxFunc)
656145449b1SDimitry Andric       Diags.Report(diag::err_incompatible_fp_eval_method_options) << 0;
657145449b1SDimitry Andric     if (LangOpts.AllowFPReassoc)
658145449b1SDimitry Andric       Diags.Report(diag::err_incompatible_fp_eval_method_options) << 1;
659145449b1SDimitry Andric     if (LangOpts.AllowRecip)
660145449b1SDimitry Andric       Diags.Report(diag::err_incompatible_fp_eval_method_options) << 2;
661145449b1SDimitry Andric   }
662145449b1SDimitry Andric 
663b60736ecSDimitry Andric   // -cl-strict-aliasing needs to emit diagnostic in the case where CL > 1.0.
664b60736ecSDimitry Andric   // This option should be deprecated for CL > 1.0 because
665b60736ecSDimitry Andric   // this option was added for compatibility with OpenCL 1.0.
666c0981da4SDimitry Andric   if (Args.getLastArg(OPT_cl_strict_aliasing) &&
667c0981da4SDimitry Andric       (LangOpts.getOpenCLCompatibleVersion() > 100))
668b60736ecSDimitry Andric     Diags.Report(diag::warn_option_invalid_ocl_version)
669c0981da4SDimitry Andric         << LangOpts.getOpenCLVersionString()
670b60736ecSDimitry Andric         << Args.getLastArg(OPT_cl_strict_aliasing)->getAsString(Args);
671b60736ecSDimitry Andric 
672b60736ecSDimitry Andric   if (Arg *A = Args.getLastArg(OPT_fdefault_calling_conv_EQ)) {
673b60736ecSDimitry Andric     auto DefaultCC = LangOpts.getDefaultCallingConv();
674b60736ecSDimitry Andric 
675b60736ecSDimitry Andric     bool emitError = (DefaultCC == LangOptions::DCC_FastCall ||
676b60736ecSDimitry Andric                       DefaultCC == LangOptions::DCC_StdCall) &&
677b60736ecSDimitry Andric                      Arch != llvm::Triple::x86;
678b60736ecSDimitry Andric     emitError |= (DefaultCC == LangOptions::DCC_VectorCall ||
679b60736ecSDimitry Andric                   DefaultCC == LangOptions::DCC_RegCall) &&
680b60736ecSDimitry Andric                  !T.isX86();
681b1c73532SDimitry Andric     emitError |= DefaultCC == LangOptions::DCC_RtdCall && Arch != llvm::Triple::m68k;
682b60736ecSDimitry Andric     if (emitError)
683b60736ecSDimitry Andric       Diags.Report(diag::err_drv_argument_not_allowed_with)
684b60736ecSDimitry Andric           << A->getSpelling() << T.getTriple();
685b60736ecSDimitry Andric   }
686b60736ecSDimitry Andric 
687344a3780SDimitry Andric   return Diags.getNumErrors() == NumErrorsBefore;
688b60736ecSDimitry Andric }
689b60736ecSDimitry Andric 
690cfca06d7SDimitry Andric //===----------------------------------------------------------------------===//
69113cc256eSDimitry Andric // Deserialization (from args)
6921569ce68SRoman Divacky //===----------------------------------------------------------------------===//
6931569ce68SRoman Divacky 
getOptimizationLevel(ArgList & Args,InputKind IK,DiagnosticsEngine & Diags)694bca07a45SDimitry Andric static unsigned getOptimizationLevel(ArgList &Args, InputKind IK,
69536981b17SDimitry Andric                                      DiagnosticsEngine &Diags) {
696b1c73532SDimitry Andric   unsigned DefaultOpt = 0;
697344a3780SDimitry Andric   if ((IK.getLanguage() == Language::OpenCL ||
698344a3780SDimitry Andric        IK.getLanguage() == Language::OpenCLCXX) &&
699344a3780SDimitry Andric       !Args.hasArg(OPT_cl_opt_disable))
700b1c73532SDimitry Andric     DefaultOpt = 2;
70156d91b49SDimitry Andric 
70256d91b49SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
70356d91b49SDimitry Andric     if (A->getOption().matches(options::OPT_O0))
704b1c73532SDimitry Andric       return 0;
70556d91b49SDimitry Andric 
7066a037251SDimitry Andric     if (A->getOption().matches(options::OPT_Ofast))
707b1c73532SDimitry Andric       return 3;
7086a037251SDimitry Andric 
70956d91b49SDimitry Andric     assert(A->getOption().matches(options::OPT_O));
71056d91b49SDimitry Andric 
711809500fcSDimitry Andric     StringRef S(A->getValue());
712cfca06d7SDimitry Andric     if (S == "s" || S == "z")
713b1c73532SDimitry Andric       return 2;
71456d91b49SDimitry Andric 
715bab175ecSDimitry Andric     if (S == "g")
716b1c73532SDimitry Andric       return 1;
717bab175ecSDimitry Andric 
718bfef3995SDimitry Andric     return getLastArgIntValue(Args, OPT_O, DefaultOpt, Diags);
71956d91b49SDimitry Andric   }
72056d91b49SDimitry Andric 
72156d91b49SDimitry Andric   return DefaultOpt;
72256d91b49SDimitry Andric }
72356d91b49SDimitry Andric 
getOptimizationLevelSize(ArgList & Args)7246a037251SDimitry Andric static unsigned getOptimizationLevelSize(ArgList &Args) {
72556d91b49SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
72656d91b49SDimitry Andric     if (A->getOption().matches(options::OPT_O)) {
72713cc256eSDimitry Andric       switch (A->getValue()[0]) {
72856d91b49SDimitry Andric       default:
72956d91b49SDimitry Andric         return 0;
73056d91b49SDimitry Andric       case 's':
73156d91b49SDimitry Andric         return 1;
73256d91b49SDimitry Andric       case 'z':
73356d91b49SDimitry Andric         return 2;
73456d91b49SDimitry Andric       }
73556d91b49SDimitry Andric     }
73656d91b49SDimitry Andric   }
73756d91b49SDimitry Andric   return 0;
73856d91b49SDimitry Andric }
73956d91b49SDimitry Andric 
GenerateArg(ArgumentConsumer Consumer,llvm::opt::OptSpecifier OptSpecifier)740b1c73532SDimitry Andric static void GenerateArg(ArgumentConsumer Consumer,
741b1c73532SDimitry Andric                         llvm::opt::OptSpecifier OptSpecifier) {
742344a3780SDimitry Andric   Option Opt = getDriverOptTable().getOption(OptSpecifier);
743b1c73532SDimitry Andric   denormalizeSimpleFlag(Consumer, Opt.getPrefixedName(),
744344a3780SDimitry Andric                         Option::OptionClass::FlagClass, 0);
745344a3780SDimitry Andric }
746344a3780SDimitry Andric 
GenerateArg(ArgumentConsumer Consumer,llvm::opt::OptSpecifier OptSpecifier,const Twine & Value)747b1c73532SDimitry Andric static void GenerateArg(ArgumentConsumer Consumer,
748344a3780SDimitry Andric                         llvm::opt::OptSpecifier OptSpecifier,
749b1c73532SDimitry Andric                         const Twine &Value) {
750344a3780SDimitry Andric   Option Opt = getDriverOptTable().getOption(OptSpecifier);
751b1c73532SDimitry Andric   denormalizeString(Consumer, Opt.getPrefixedName(), Opt.getKind(), 0, Value);
752344a3780SDimitry Andric }
753344a3780SDimitry Andric 
754344a3780SDimitry Andric // Parse command line arguments into CompilerInvocation.
755344a3780SDimitry Andric using ParseFn =
756344a3780SDimitry Andric     llvm::function_ref<bool(CompilerInvocation &, ArrayRef<const char *>,
757344a3780SDimitry Andric                             DiagnosticsEngine &, const char *)>;
758344a3780SDimitry Andric 
759344a3780SDimitry Andric // Generate command line arguments from CompilerInvocation.
760344a3780SDimitry Andric using GenerateFn = llvm::function_ref<void(
761344a3780SDimitry Andric     CompilerInvocation &, SmallVectorImpl<const char *> &,
762344a3780SDimitry Andric     CompilerInvocation::StringAllocator)>;
763344a3780SDimitry Andric 
7647fa27ce4SDimitry Andric /// May perform round-trip of command line arguments. By default, the round-trip
7657fa27ce4SDimitry Andric /// is enabled in assert builds. This can be overwritten at run-time via the
7667fa27ce4SDimitry Andric /// "-round-trip-args" and "-no-round-trip-args" command line flags, or via the
7677fa27ce4SDimitry Andric /// ForceRoundTrip parameter.
7687fa27ce4SDimitry Andric ///
7697fa27ce4SDimitry Andric /// During round-trip, the command line arguments are parsed into a dummy
7707fa27ce4SDimitry Andric /// CompilerInvocation, which is used to generate the command line arguments
7717fa27ce4SDimitry Andric /// again. The real CompilerInvocation is then created by parsing the generated
7727fa27ce4SDimitry Andric /// arguments, not the original ones. This (in combination with tests covering
7737fa27ce4SDimitry Andric /// argument behavior) ensures the generated command line is complete (doesn't
7747fa27ce4SDimitry Andric /// drop/mangle any arguments).
7757fa27ce4SDimitry Andric ///
7767fa27ce4SDimitry Andric /// Finally, we check the command line that was used to create the real
7777fa27ce4SDimitry Andric /// CompilerInvocation instance. By default, we compare it to the command line
7787fa27ce4SDimitry Andric /// the real CompilerInvocation generates. This checks whether the generator is
7797fa27ce4SDimitry Andric /// deterministic. If \p CheckAgainstOriginalInvocation is enabled, we instead
7807fa27ce4SDimitry Andric /// compare it to the original command line to verify the original command-line
7817fa27ce4SDimitry Andric /// was canonical and can round-trip exactly.
RoundTrip(ParseFn Parse,GenerateFn Generate,CompilerInvocation & RealInvocation,CompilerInvocation & DummyInvocation,ArrayRef<const char * > CommandLineArgs,DiagnosticsEngine & Diags,const char * Argv0,bool CheckAgainstOriginalInvocation=false,bool ForceRoundTrip=false)782344a3780SDimitry Andric static bool RoundTrip(ParseFn Parse, GenerateFn Generate,
783344a3780SDimitry Andric                       CompilerInvocation &RealInvocation,
784344a3780SDimitry Andric                       CompilerInvocation &DummyInvocation,
785344a3780SDimitry Andric                       ArrayRef<const char *> CommandLineArgs,
7867fa27ce4SDimitry Andric                       DiagnosticsEngine &Diags, const char *Argv0,
7877fa27ce4SDimitry Andric                       bool CheckAgainstOriginalInvocation = false,
7887fa27ce4SDimitry Andric                       bool ForceRoundTrip = false) {
789c0981da4SDimitry Andric #ifndef NDEBUG
790344a3780SDimitry Andric   bool DoRoundTripDefault = true;
791344a3780SDimitry Andric #else
792344a3780SDimitry Andric   bool DoRoundTripDefault = false;
793344a3780SDimitry Andric #endif
794344a3780SDimitry Andric 
795344a3780SDimitry Andric   bool DoRoundTrip = DoRoundTripDefault;
7967fa27ce4SDimitry Andric   if (ForceRoundTrip) {
7977fa27ce4SDimitry Andric     DoRoundTrip = true;
7987fa27ce4SDimitry Andric   } else {
799344a3780SDimitry Andric     for (const auto *Arg : CommandLineArgs) {
800344a3780SDimitry Andric       if (Arg == StringRef("-round-trip-args"))
801344a3780SDimitry Andric         DoRoundTrip = true;
802344a3780SDimitry Andric       if (Arg == StringRef("-no-round-trip-args"))
803344a3780SDimitry Andric         DoRoundTrip = false;
804344a3780SDimitry Andric     }
8057fa27ce4SDimitry Andric   }
806344a3780SDimitry Andric 
807344a3780SDimitry Andric   // If round-trip was not requested, simply run the parser with the real
808344a3780SDimitry Andric   // invocation diagnostics.
809344a3780SDimitry Andric   if (!DoRoundTrip)
810344a3780SDimitry Andric     return Parse(RealInvocation, CommandLineArgs, Diags, Argv0);
811344a3780SDimitry Andric 
812344a3780SDimitry Andric   // Serializes quoted (and potentially escaped) arguments.
813344a3780SDimitry Andric   auto SerializeArgs = [](ArrayRef<const char *> Args) {
814344a3780SDimitry Andric     std::string Buffer;
815344a3780SDimitry Andric     llvm::raw_string_ostream OS(Buffer);
816344a3780SDimitry Andric     for (const char *Arg : Args) {
817344a3780SDimitry Andric       llvm::sys::printArg(OS, Arg, /*Quote=*/true);
818344a3780SDimitry Andric       OS << ' ';
819344a3780SDimitry Andric     }
820344a3780SDimitry Andric     OS.flush();
821344a3780SDimitry Andric     return Buffer;
822344a3780SDimitry Andric   };
823344a3780SDimitry Andric 
824344a3780SDimitry Andric   // Setup a dummy DiagnosticsEngine.
825344a3780SDimitry Andric   DiagnosticsEngine DummyDiags(new DiagnosticIDs(), new DiagnosticOptions());
826344a3780SDimitry Andric   DummyDiags.setClient(new TextDiagnosticBuffer());
827344a3780SDimitry Andric 
828344a3780SDimitry Andric   // Run the first parse on the original arguments with the dummy invocation and
829344a3780SDimitry Andric   // diagnostics.
830344a3780SDimitry Andric   if (!Parse(DummyInvocation, CommandLineArgs, DummyDiags, Argv0) ||
831344a3780SDimitry Andric       DummyDiags.getNumWarnings() != 0) {
832344a3780SDimitry Andric     // If the first parse did not succeed, it must be user mistake (invalid
833344a3780SDimitry Andric     // command line arguments). We won't be able to generate arguments that
834344a3780SDimitry Andric     // would reproduce the same result. Let's fail again with the real
835344a3780SDimitry Andric     // invocation and diagnostics, so all side-effects of parsing are visible.
836344a3780SDimitry Andric     unsigned NumWarningsBefore = Diags.getNumWarnings();
837344a3780SDimitry Andric     auto Success = Parse(RealInvocation, CommandLineArgs, Diags, Argv0);
838344a3780SDimitry Andric     if (!Success || Diags.getNumWarnings() != NumWarningsBefore)
839344a3780SDimitry Andric       return Success;
840344a3780SDimitry Andric 
841344a3780SDimitry Andric     // Parse with original options and diagnostics succeeded even though it
842344a3780SDimitry Andric     // shouldn't have. Something is off.
843344a3780SDimitry Andric     Diags.Report(diag::err_cc1_round_trip_fail_then_ok);
844344a3780SDimitry Andric     Diags.Report(diag::note_cc1_round_trip_original)
845344a3780SDimitry Andric         << SerializeArgs(CommandLineArgs);
846344a3780SDimitry Andric     return false;
847344a3780SDimitry Andric   }
848344a3780SDimitry Andric 
849344a3780SDimitry Andric   // Setup string allocator.
850344a3780SDimitry Andric   llvm::BumpPtrAllocator Alloc;
851344a3780SDimitry Andric   llvm::StringSaver StringPool(Alloc);
852344a3780SDimitry Andric   auto SA = [&StringPool](const Twine &Arg) {
853344a3780SDimitry Andric     return StringPool.save(Arg).data();
854344a3780SDimitry Andric   };
855344a3780SDimitry Andric 
856344a3780SDimitry Andric   // Generate arguments from the dummy invocation. If Generate is the
857344a3780SDimitry Andric   // inverse of Parse, the newly generated arguments must have the same
858344a3780SDimitry Andric   // semantics as the original.
8597fa27ce4SDimitry Andric   SmallVector<const char *> GeneratedArgs;
8607fa27ce4SDimitry Andric   Generate(DummyInvocation, GeneratedArgs, SA);
861344a3780SDimitry Andric 
862344a3780SDimitry Andric   // Run the second parse, now on the generated arguments, and with the real
863344a3780SDimitry Andric   // invocation and diagnostics. The result is what we will end up using for the
864344a3780SDimitry Andric   // rest of compilation, so if Generate is not inverse of Parse, something down
865344a3780SDimitry Andric   // the line will break.
8667fa27ce4SDimitry Andric   bool Success2 = Parse(RealInvocation, GeneratedArgs, Diags, Argv0);
867344a3780SDimitry Andric 
868344a3780SDimitry Andric   // The first parse on original arguments succeeded, but second parse of
869344a3780SDimitry Andric   // generated arguments failed. Something must be wrong with the generator.
870344a3780SDimitry Andric   if (!Success2) {
871344a3780SDimitry Andric     Diags.Report(diag::err_cc1_round_trip_ok_then_fail);
872344a3780SDimitry Andric     Diags.Report(diag::note_cc1_round_trip_generated)
8737fa27ce4SDimitry Andric         << 1 << SerializeArgs(GeneratedArgs);
874344a3780SDimitry Andric     return false;
875344a3780SDimitry Andric   }
876344a3780SDimitry Andric 
8777fa27ce4SDimitry Andric   SmallVector<const char *> ComparisonArgs;
8787fa27ce4SDimitry Andric   if (CheckAgainstOriginalInvocation)
8797fa27ce4SDimitry Andric     // Compare against original arguments.
8807fa27ce4SDimitry Andric     ComparisonArgs.assign(CommandLineArgs.begin(), CommandLineArgs.end());
8817fa27ce4SDimitry Andric   else
882344a3780SDimitry Andric     // Generate arguments again, this time from the options we will end up using
883344a3780SDimitry Andric     // for the rest of the compilation.
8847fa27ce4SDimitry Andric     Generate(RealInvocation, ComparisonArgs, SA);
885344a3780SDimitry Andric 
8867fa27ce4SDimitry Andric   // Compares two lists of arguments.
887344a3780SDimitry Andric   auto Equal = [](const ArrayRef<const char *> A,
888344a3780SDimitry Andric                   const ArrayRef<const char *> B) {
889344a3780SDimitry Andric     return std::equal(A.begin(), A.end(), B.begin(), B.end(),
890344a3780SDimitry Andric                       [](const char *AElem, const char *BElem) {
891344a3780SDimitry Andric                         return StringRef(AElem) == StringRef(BElem);
892344a3780SDimitry Andric                       });
893344a3780SDimitry Andric   };
894344a3780SDimitry Andric 
895344a3780SDimitry Andric   // If we generated different arguments from what we assume are two
896344a3780SDimitry Andric   // semantically equivalent CompilerInvocations, the Generate function may
897344a3780SDimitry Andric   // be non-deterministic.
8987fa27ce4SDimitry Andric   if (!Equal(GeneratedArgs, ComparisonArgs)) {
899344a3780SDimitry Andric     Diags.Report(diag::err_cc1_round_trip_mismatch);
900344a3780SDimitry Andric     Diags.Report(diag::note_cc1_round_trip_generated)
9017fa27ce4SDimitry Andric         << 1 << SerializeArgs(GeneratedArgs);
902344a3780SDimitry Andric     Diags.Report(diag::note_cc1_round_trip_generated)
9037fa27ce4SDimitry Andric         << 2 << SerializeArgs(ComparisonArgs);
904344a3780SDimitry Andric     return false;
905344a3780SDimitry Andric   }
906344a3780SDimitry Andric 
907344a3780SDimitry Andric   Diags.Report(diag::remark_cc1_round_trip_generated)
9087fa27ce4SDimitry Andric       << 1 << SerializeArgs(GeneratedArgs);
909344a3780SDimitry Andric   Diags.Report(diag::remark_cc1_round_trip_generated)
9107fa27ce4SDimitry Andric       << 2 << SerializeArgs(ComparisonArgs);
911344a3780SDimitry Andric 
912344a3780SDimitry Andric   return Success2;
913b60736ecSDimitry Andric }
914b60736ecSDimitry Andric 
checkCC1RoundTrip(ArrayRef<const char * > Args,DiagnosticsEngine & Diags,const char * Argv0)9157fa27ce4SDimitry Andric bool CompilerInvocation::checkCC1RoundTrip(ArrayRef<const char *> Args,
9167fa27ce4SDimitry Andric                                            DiagnosticsEngine &Diags,
9177fa27ce4SDimitry Andric                                            const char *Argv0) {
9187fa27ce4SDimitry Andric   CompilerInvocation DummyInvocation1, DummyInvocation2;
9197fa27ce4SDimitry Andric   return RoundTrip(
9207fa27ce4SDimitry Andric       [](CompilerInvocation &Invocation, ArrayRef<const char *> CommandLineArgs,
9217fa27ce4SDimitry Andric          DiagnosticsEngine &Diags, const char *Argv0) {
9227fa27ce4SDimitry Andric         return CreateFromArgsImpl(Invocation, CommandLineArgs, Diags, Argv0);
9237fa27ce4SDimitry Andric       },
9247fa27ce4SDimitry Andric       [](CompilerInvocation &Invocation, SmallVectorImpl<const char *> &Args,
9257fa27ce4SDimitry Andric          StringAllocator SA) {
9267fa27ce4SDimitry Andric         Args.push_back("-cc1");
9277fa27ce4SDimitry Andric         Invocation.generateCC1CommandLine(Args, SA);
9287fa27ce4SDimitry Andric       },
9297fa27ce4SDimitry Andric       DummyInvocation1, DummyInvocation2, Args, Diags, Argv0,
9307fa27ce4SDimitry Andric       /*CheckAgainstOriginalInvocation=*/true, /*ForceRoundTrip=*/true);
9317fa27ce4SDimitry Andric }
9327fa27ce4SDimitry Andric 
addDiagnosticArgs(ArgList & Args,OptSpecifier Group,OptSpecifier GroupWithValue,std::vector<std::string> & Diagnostics)9339f4dbff6SDimitry Andric static void addDiagnosticArgs(ArgList &Args, OptSpecifier Group,
9349f4dbff6SDimitry Andric                               OptSpecifier GroupWithValue,
9359f4dbff6SDimitry Andric                               std::vector<std::string> &Diagnostics) {
93648675466SDimitry Andric   for (auto *A : Args.filtered(Group)) {
93756d91b49SDimitry Andric     if (A->getOption().getKind() == Option::FlagClass) {
9389f4dbff6SDimitry Andric       // The argument is a pure flag (such as OPT_Wall or OPT_Wdeprecated). Add
939344a3780SDimitry Andric       // its name (minus the "W" or "R" at the beginning) to the diagnostics.
940cfca06d7SDimitry Andric       Diagnostics.push_back(
941cfca06d7SDimitry Andric           std::string(A->getOption().getName().drop_front(1)));
9429f4dbff6SDimitry Andric     } else if (A->getOption().matches(GroupWithValue)) {
943344a3780SDimitry Andric       // This is -Wfoo= or -Rfoo=, where foo is the name of the diagnostic
944344a3780SDimitry Andric       // group. Add only the group name to the diagnostics.
945cfca06d7SDimitry Andric       Diagnostics.push_back(
946cfca06d7SDimitry Andric           std::string(A->getOption().getName().drop_front(1).rtrim("=-")));
94756d91b49SDimitry Andric     } else {
9489f4dbff6SDimitry Andric       // Otherwise, add its value (for OPT_W_Joined and similar).
949344a3780SDimitry Andric       Diagnostics.push_back(A->getValue());
95056d91b49SDimitry Andric     }
95156d91b49SDimitry Andric   }
952bca07a45SDimitry Andric }
953bca07a45SDimitry Andric 
954676fbe81SDimitry Andric // Parse the Static Analyzer configuration. If \p Diags is set to nullptr,
955676fbe81SDimitry Andric // it won't verify the input.
956676fbe81SDimitry Andric static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts,
957676fbe81SDimitry Andric                                  DiagnosticsEngine *Diags);
958676fbe81SDimitry Andric 
getAllNoBuiltinFuncValues(ArgList & Args,std::vector<std::string> & Funcs)95997b17066SDimitry Andric static void getAllNoBuiltinFuncValues(ArgList &Args,
96097b17066SDimitry Andric                                       std::vector<std::string> &Funcs) {
961344a3780SDimitry Andric   std::vector<std::string> Values = Args.getAllArgValues(OPT_fno_builtin_);
96277fc4c14SDimitry Andric   auto BuiltinEnd = llvm::partition(Values, Builtin::Context::isBuiltinFunc);
963344a3780SDimitry Andric   Funcs.insert(Funcs.end(), Values.begin(), BuiltinEnd);
964344a3780SDimitry Andric }
965344a3780SDimitry Andric 
GenerateAnalyzerArgs(const AnalyzerOptions & Opts,ArgumentConsumer Consumer)966b1c73532SDimitry Andric static void GenerateAnalyzerArgs(const AnalyzerOptions &Opts,
967b1c73532SDimitry Andric                                  ArgumentConsumer Consumer) {
968344a3780SDimitry Andric   const AnalyzerOptions *AnalyzerOpts = &Opts;
969344a3780SDimitry Andric 
9707fa27ce4SDimitry Andric #define ANALYZER_OPTION_WITH_MARSHALLING(...)                                  \
971b1c73532SDimitry Andric   GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
972344a3780SDimitry Andric #include "clang/Driver/Options.inc"
973344a3780SDimitry Andric #undef ANALYZER_OPTION_WITH_MARSHALLING
974344a3780SDimitry Andric 
975344a3780SDimitry Andric   if (Opts.AnalysisConstraintsOpt != RangeConstraintsModel) {
976344a3780SDimitry Andric     switch (Opts.AnalysisConstraintsOpt) {
977344a3780SDimitry Andric #define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN)                     \
978344a3780SDimitry Andric   case NAME##Model:                                                            \
979b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_analyzer_constraints, CMDFLAG);                  \
980344a3780SDimitry Andric     break;
981344a3780SDimitry Andric #include "clang/StaticAnalyzer/Core/Analyses.def"
982344a3780SDimitry Andric     default:
983344a3780SDimitry Andric       llvm_unreachable("Tried to generate unknown analysis constraint.");
984344a3780SDimitry Andric     }
985344a3780SDimitry Andric   }
986344a3780SDimitry Andric 
987344a3780SDimitry Andric   if (Opts.AnalysisDiagOpt != PD_HTML) {
988344a3780SDimitry Andric     switch (Opts.AnalysisDiagOpt) {
989344a3780SDimitry Andric #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN)                     \
990344a3780SDimitry Andric   case PD_##NAME:                                                              \
991b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_analyzer_output, CMDFLAG);                       \
992344a3780SDimitry Andric     break;
993344a3780SDimitry Andric #include "clang/StaticAnalyzer/Core/Analyses.def"
994344a3780SDimitry Andric     default:
995344a3780SDimitry Andric       llvm_unreachable("Tried to generate unknown analysis diagnostic client.");
996344a3780SDimitry Andric     }
997344a3780SDimitry Andric   }
998344a3780SDimitry Andric 
999344a3780SDimitry Andric   if (Opts.AnalysisPurgeOpt != PurgeStmt) {
1000344a3780SDimitry Andric     switch (Opts.AnalysisPurgeOpt) {
1001344a3780SDimitry Andric #define ANALYSIS_PURGE(NAME, CMDFLAG, DESC)                                    \
1002344a3780SDimitry Andric   case NAME:                                                                   \
1003b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_analyzer_purge, CMDFLAG);                        \
1004344a3780SDimitry Andric     break;
1005344a3780SDimitry Andric #include "clang/StaticAnalyzer/Core/Analyses.def"
1006344a3780SDimitry Andric     default:
1007344a3780SDimitry Andric       llvm_unreachable("Tried to generate unknown analysis purge mode.");
1008344a3780SDimitry Andric     }
1009344a3780SDimitry Andric   }
1010344a3780SDimitry Andric 
1011344a3780SDimitry Andric   if (Opts.InliningMode != NoRedundancy) {
1012344a3780SDimitry Andric     switch (Opts.InliningMode) {
1013344a3780SDimitry Andric #define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC)                            \
1014344a3780SDimitry Andric   case NAME:                                                                   \
1015b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_analyzer_inlining_mode, CMDFLAG);                \
1016344a3780SDimitry Andric     break;
1017344a3780SDimitry Andric #include "clang/StaticAnalyzer/Core/Analyses.def"
1018344a3780SDimitry Andric     default:
1019344a3780SDimitry Andric       llvm_unreachable("Tried to generate unknown analysis inlining mode.");
1020344a3780SDimitry Andric     }
1021344a3780SDimitry Andric   }
1022344a3780SDimitry Andric 
1023344a3780SDimitry Andric   for (const auto &CP : Opts.CheckersAndPackages) {
1024344a3780SDimitry Andric     OptSpecifier Opt =
1025344a3780SDimitry Andric         CP.second ? OPT_analyzer_checker : OPT_analyzer_disable_checker;
1026b1c73532SDimitry Andric     GenerateArg(Consumer, Opt, CP.first);
1027344a3780SDimitry Andric   }
1028344a3780SDimitry Andric 
1029344a3780SDimitry Andric   AnalyzerOptions ConfigOpts;
1030344a3780SDimitry Andric   parseAnalyzerConfigs(ConfigOpts, nullptr);
1031344a3780SDimitry Andric 
10327fa27ce4SDimitry Andric   // Sort options by key to avoid relying on StringMap iteration order.
10337fa27ce4SDimitry Andric   SmallVector<std::pair<StringRef, StringRef>, 4> SortedConfigOpts;
10347fa27ce4SDimitry Andric   for (const auto &C : Opts.Config)
10357fa27ce4SDimitry Andric     SortedConfigOpts.emplace_back(C.getKey(), C.getValue());
10367fa27ce4SDimitry Andric   llvm::sort(SortedConfigOpts, llvm::less_first());
10377fa27ce4SDimitry Andric 
10387fa27ce4SDimitry Andric   for (const auto &[Key, Value] : SortedConfigOpts) {
1039344a3780SDimitry Andric     // Don't generate anything that came from parseAnalyzerConfigs. It would be
1040344a3780SDimitry Andric     // redundant and may not be valid on the command line.
10417fa27ce4SDimitry Andric     auto Entry = ConfigOpts.Config.find(Key);
10427fa27ce4SDimitry Andric     if (Entry != ConfigOpts.Config.end() && Entry->getValue() == Value)
1043344a3780SDimitry Andric       continue;
1044344a3780SDimitry Andric 
1045b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_analyzer_config, Key + "=" + Value);
1046344a3780SDimitry Andric   }
1047344a3780SDimitry Andric 
1048344a3780SDimitry Andric   // Nothing to generate for FullCompilerInvocation.
104997b17066SDimitry Andric }
105097b17066SDimitry Andric 
ParseAnalyzerArgs(AnalyzerOptions & Opts,ArgList & Args,DiagnosticsEngine & Diags)1051dbe13110SDimitry Andric static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
105236981b17SDimitry Andric                               DiagnosticsEngine &Diags) {
1053344a3780SDimitry Andric   unsigned NumErrorsBefore = Diags.getNumErrors();
1054344a3780SDimitry Andric 
1055344a3780SDimitry Andric   AnalyzerOptions *AnalyzerOpts = &Opts;
1056344a3780SDimitry Andric 
10577fa27ce4SDimitry Andric #define ANALYZER_OPTION_WITH_MARSHALLING(...)                                  \
10587fa27ce4SDimitry Andric   PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
1059344a3780SDimitry Andric #include "clang/Driver/Options.inc"
1060344a3780SDimitry Andric #undef ANALYZER_OPTION_WITH_MARSHALLING
1061344a3780SDimitry Andric 
10621569ce68SRoman Divacky   if (Arg *A = Args.getLastArg(OPT_analyzer_constraints)) {
106313cc256eSDimitry Andric     StringRef Name = A->getValue();
10641569ce68SRoman Divacky     AnalysisConstraints Value = llvm::StringSwitch<AnalysisConstraints>(Name)
10651569ce68SRoman Divacky #define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \
10661569ce68SRoman Divacky       .Case(CMDFLAG, NAME##Model)
106713cc256eSDimitry Andric #include "clang/StaticAnalyzer/Core/Analyses.def"
10681569ce68SRoman Divacky       .Default(NumConstraints);
1069dbe13110SDimitry Andric     if (Value == NumConstraints) {
10701569ce68SRoman Divacky       Diags.Report(diag::err_drv_invalid_value)
10714ba67500SRoman Divacky         << A->getAsString(Args) << Name;
1072dbe13110SDimitry Andric     } else {
1073145449b1SDimitry Andric #ifndef LLVM_WITH_Z3
1074145449b1SDimitry Andric       if (Value == AnalysisConstraints::Z3ConstraintsModel) {
1075145449b1SDimitry Andric         Diags.Report(diag::err_analyzer_not_built_with_z3);
1076145449b1SDimitry Andric       }
1077145449b1SDimitry Andric #endif // LLVM_WITH_Z3
10781569ce68SRoman Divacky       Opts.AnalysisConstraintsOpt = Value;
10791569ce68SRoman Divacky     }
1080dbe13110SDimitry Andric   }
10811569ce68SRoman Divacky 
10821569ce68SRoman Divacky   if (Arg *A = Args.getLastArg(OPT_analyzer_output)) {
108313cc256eSDimitry Andric     StringRef Name = A->getValue();
10841569ce68SRoman Divacky     AnalysisDiagClients Value = llvm::StringSwitch<AnalysisDiagClients>(Name)
1085bfef3995SDimitry Andric #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) \
10861569ce68SRoman Divacky       .Case(CMDFLAG, PD_##NAME)
108713cc256eSDimitry Andric #include "clang/StaticAnalyzer/Core/Analyses.def"
10881569ce68SRoman Divacky       .Default(NUM_ANALYSIS_DIAG_CLIENTS);
1089dbe13110SDimitry Andric     if (Value == NUM_ANALYSIS_DIAG_CLIENTS) {
10901569ce68SRoman Divacky       Diags.Report(diag::err_drv_invalid_value)
10914ba67500SRoman Divacky         << A->getAsString(Args) << Name;
1092dbe13110SDimitry Andric     } else {
10931569ce68SRoman Divacky       Opts.AnalysisDiagOpt = Value;
10941569ce68SRoman Divacky     }
1095dbe13110SDimitry Andric   }
10961569ce68SRoman Divacky 
109736981b17SDimitry Andric   if (Arg *A = Args.getLastArg(OPT_analyzer_purge)) {
109813cc256eSDimitry Andric     StringRef Name = A->getValue();
109936981b17SDimitry Andric     AnalysisPurgeMode Value = llvm::StringSwitch<AnalysisPurgeMode>(Name)
110036981b17SDimitry Andric #define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) \
110136981b17SDimitry Andric       .Case(CMDFLAG, NAME)
110213cc256eSDimitry Andric #include "clang/StaticAnalyzer/Core/Analyses.def"
110336981b17SDimitry Andric       .Default(NumPurgeModes);
1104dbe13110SDimitry Andric     if (Value == NumPurgeModes) {
110536981b17SDimitry Andric       Diags.Report(diag::err_drv_invalid_value)
110636981b17SDimitry Andric         << A->getAsString(Args) << Name;
1107dbe13110SDimitry Andric     } else {
110836981b17SDimitry Andric       Opts.AnalysisPurgeOpt = Value;
110936981b17SDimitry Andric     }
1110dbe13110SDimitry Andric   }
1111dbe13110SDimitry Andric 
1112dbe13110SDimitry Andric   if (Arg *A = Args.getLastArg(OPT_analyzer_inlining_mode)) {
111313cc256eSDimitry Andric     StringRef Name = A->getValue();
1114dbe13110SDimitry Andric     AnalysisInliningMode Value = llvm::StringSwitch<AnalysisInliningMode>(Name)
1115dbe13110SDimitry Andric #define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) \
1116dbe13110SDimitry Andric       .Case(CMDFLAG, NAME)
111713cc256eSDimitry Andric #include "clang/StaticAnalyzer/Core/Analyses.def"
1118dbe13110SDimitry Andric       .Default(NumInliningModes);
1119dbe13110SDimitry Andric     if (Value == NumInliningModes) {
1120dbe13110SDimitry Andric       Diags.Report(diag::err_drv_invalid_value)
1121dbe13110SDimitry Andric         << A->getAsString(Args) << Name;
1122dbe13110SDimitry Andric     } else {
1123dbe13110SDimitry Andric       Opts.InliningMode = Value;
1124dbe13110SDimitry Andric     }
1125dbe13110SDimitry Andric   }
112636981b17SDimitry Andric 
1127519fc96cSDimitry Andric   Opts.CheckersAndPackages.clear();
1128798321d8SDimitry Andric   for (const Arg *A :
1129798321d8SDimitry Andric        Args.filtered(OPT_analyzer_checker, OPT_analyzer_disable_checker)) {
1130bca07a45SDimitry Andric     A->claim();
1131519fc96cSDimitry Andric     bool IsEnabled = A->getOption().getID() == OPT_analyzer_checker;
1132c3b054d2SDimitry Andric     // We can have a list of comma separated checker names, e.g:
1133c3b054d2SDimitry Andric     // '-analyzer-checker=cocoa,unix'
1134519fc96cSDimitry Andric     StringRef CheckerAndPackageList = A->getValue();
1135519fc96cSDimitry Andric     SmallVector<StringRef, 16> CheckersAndPackages;
1136519fc96cSDimitry Andric     CheckerAndPackageList.split(CheckersAndPackages, ",");
1137706b4fc4SDimitry Andric     for (const StringRef &CheckerOrPackage : CheckersAndPackages)
1138cfca06d7SDimitry Andric       Opts.CheckersAndPackages.emplace_back(std::string(CheckerOrPackage),
1139cfca06d7SDimitry Andric                                             IsEnabled);
1140bca07a45SDimitry Andric   }
1141dbe13110SDimitry Andric 
114213cc256eSDimitry Andric   // Go through the analyzer configuration options.
114348675466SDimitry Andric   for (const auto *A : Args.filtered(OPT_analyzer_config)) {
1144676fbe81SDimitry Andric 
114513cc256eSDimitry Andric     // We can have a list of comma separated config names, e.g:
114613cc256eSDimitry Andric     // '-analyzer-config key1=val1,key2=val2'
114713cc256eSDimitry Andric     StringRef configList = A->getValue();
114813cc256eSDimitry Andric     SmallVector<StringRef, 4> configVals;
114913cc256eSDimitry Andric     configList.split(configVals, ",");
115048675466SDimitry Andric     for (const auto &configVal : configVals) {
115113cc256eSDimitry Andric       StringRef key, val;
115248675466SDimitry Andric       std::tie(key, val) = configVal.split("=");
115313cc256eSDimitry Andric       if (val.empty()) {
115413cc256eSDimitry Andric         Diags.Report(SourceLocation(),
115548675466SDimitry Andric                      diag::err_analyzer_config_no_value) << configVal;
115613cc256eSDimitry Andric         break;
115713cc256eSDimitry Andric       }
1158c0981da4SDimitry Andric       if (val.contains('=')) {
115913cc256eSDimitry Andric         Diags.Report(SourceLocation(),
116013cc256eSDimitry Andric                      diag::err_analyzer_config_multiple_values)
116148675466SDimitry Andric           << configVal;
116213cc256eSDimitry Andric         break;
116313cc256eSDimitry Andric       }
1164676fbe81SDimitry Andric 
1165676fbe81SDimitry Andric       // TODO: Check checker options too, possibly in CheckerRegistry.
1166676fbe81SDimitry Andric       // Leave unknown non-checker configs unclaimed.
1167676fbe81SDimitry Andric       if (!key.contains(":") && Opts.isUnknownAnalyzerConfig(key)) {
1168676fbe81SDimitry Andric         if (Opts.ShouldEmitErrorsOnInvalidConfigValue)
1169676fbe81SDimitry Andric           Diags.Report(diag::err_analyzer_config_unknown) << key;
1170676fbe81SDimitry Andric         continue;
1171676fbe81SDimitry Andric       }
1172676fbe81SDimitry Andric 
1173676fbe81SDimitry Andric       A->claim();
1174cfca06d7SDimitry Andric       Opts.Config[key] = std::string(val);
117513cc256eSDimitry Andric     }
117613cc256eSDimitry Andric   }
117713cc256eSDimitry Andric 
1178676fbe81SDimitry Andric   if (Opts.ShouldEmitErrorsOnInvalidConfigValue)
1179676fbe81SDimitry Andric     parseAnalyzerConfigs(Opts, &Diags);
1180676fbe81SDimitry Andric   else
1181676fbe81SDimitry Andric     parseAnalyzerConfigs(Opts, nullptr);
1182676fbe81SDimitry Andric 
118348675466SDimitry Andric   llvm::raw_string_ostream os(Opts.FullCompilerInvocation);
118448675466SDimitry Andric   for (unsigned i = 0; i < Args.getNumInputArgStrings(); ++i) {
118548675466SDimitry Andric     if (i != 0)
118648675466SDimitry Andric       os << " ";
118748675466SDimitry Andric     os << Args.getArgString(i);
118848675466SDimitry Andric   }
118948675466SDimitry Andric   os.flush();
119048675466SDimitry Andric 
1191344a3780SDimitry Andric   return Diags.getNumErrors() == NumErrorsBefore;
11921569ce68SRoman Divacky }
11931569ce68SRoman Divacky 
getStringOption(AnalyzerOptions::ConfigTable & Config,StringRef OptionName,StringRef DefaultVal)1194676fbe81SDimitry Andric static StringRef getStringOption(AnalyzerOptions::ConfigTable &Config,
1195676fbe81SDimitry Andric                                  StringRef OptionName, StringRef DefaultVal) {
1196cfca06d7SDimitry Andric   return Config.insert({OptionName, std::string(DefaultVal)}).first->second;
1197676fbe81SDimitry Andric }
1198676fbe81SDimitry Andric 
initOption(AnalyzerOptions::ConfigTable & Config,DiagnosticsEngine * Diags,StringRef & OptionField,StringRef Name,StringRef DefaultVal)1199676fbe81SDimitry Andric static void initOption(AnalyzerOptions::ConfigTable &Config,
1200676fbe81SDimitry Andric                        DiagnosticsEngine *Diags,
1201676fbe81SDimitry Andric                        StringRef &OptionField, StringRef Name,
1202676fbe81SDimitry Andric                        StringRef DefaultVal) {
1203676fbe81SDimitry Andric   // String options may be known to invalid (e.g. if the expected string is a
1204676fbe81SDimitry Andric   // file name, but the file does not exist), those will have to be checked in
1205676fbe81SDimitry Andric   // parseConfigs.
1206676fbe81SDimitry Andric   OptionField = getStringOption(Config, Name, DefaultVal);
1207676fbe81SDimitry Andric }
1208676fbe81SDimitry Andric 
initOption(AnalyzerOptions::ConfigTable & Config,DiagnosticsEngine * Diags,bool & OptionField,StringRef Name,bool DefaultVal)1209676fbe81SDimitry Andric static void initOption(AnalyzerOptions::ConfigTable &Config,
1210676fbe81SDimitry Andric                        DiagnosticsEngine *Diags,
1211676fbe81SDimitry Andric                        bool &OptionField, StringRef Name, bool DefaultVal) {
1212e3b55780SDimitry Andric   auto PossiblyInvalidVal =
1213e3b55780SDimitry Andric       llvm::StringSwitch<std::optional<bool>>(
1214676fbe81SDimitry Andric           getStringOption(Config, Name, (DefaultVal ? "true" : "false")))
1215676fbe81SDimitry Andric           .Case("true", true)
1216676fbe81SDimitry Andric           .Case("false", false)
1217e3b55780SDimitry Andric           .Default(std::nullopt);
1218676fbe81SDimitry Andric 
1219676fbe81SDimitry Andric   if (!PossiblyInvalidVal) {
1220676fbe81SDimitry Andric     if (Diags)
1221676fbe81SDimitry Andric       Diags->Report(diag::err_analyzer_config_invalid_input)
1222676fbe81SDimitry Andric         << Name << "a boolean";
1223676fbe81SDimitry Andric     else
1224676fbe81SDimitry Andric       OptionField = DefaultVal;
1225676fbe81SDimitry Andric   } else
1226145449b1SDimitry Andric     OptionField = *PossiblyInvalidVal;
1227676fbe81SDimitry Andric }
1228676fbe81SDimitry Andric 
initOption(AnalyzerOptions::ConfigTable & Config,DiagnosticsEngine * Diags,unsigned & OptionField,StringRef Name,unsigned DefaultVal)1229676fbe81SDimitry Andric static void initOption(AnalyzerOptions::ConfigTable &Config,
1230676fbe81SDimitry Andric                        DiagnosticsEngine *Diags,
1231676fbe81SDimitry Andric                        unsigned &OptionField, StringRef Name,
1232676fbe81SDimitry Andric                        unsigned DefaultVal) {
1233676fbe81SDimitry Andric 
1234676fbe81SDimitry Andric   OptionField = DefaultVal;
1235676fbe81SDimitry Andric   bool HasFailed = getStringOption(Config, Name, std::to_string(DefaultVal))
123622989816SDimitry Andric                      .getAsInteger(0, OptionField);
1237676fbe81SDimitry Andric   if (Diags && HasFailed)
1238676fbe81SDimitry Andric     Diags->Report(diag::err_analyzer_config_invalid_input)
1239676fbe81SDimitry Andric       << Name << "an unsigned";
1240676fbe81SDimitry Andric }
1241676fbe81SDimitry Andric 
parseAnalyzerConfigs(AnalyzerOptions & AnOpts,DiagnosticsEngine * Diags)1242676fbe81SDimitry Andric static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts,
1243676fbe81SDimitry Andric                                  DiagnosticsEngine *Diags) {
1244676fbe81SDimitry Andric   // TODO: There's no need to store the entire configtable, it'd be plenty
1245676fbe81SDimitry Andric   // enough to store checker options.
1246676fbe81SDimitry Andric 
1247676fbe81SDimitry Andric #define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL)                \
1248676fbe81SDimitry Andric   initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG, DEFAULT_VAL);
1249145449b1SDimitry Andric #define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(...)
1250145449b1SDimitry Andric #include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
1251676fbe81SDimitry Andric 
1252145449b1SDimitry Andric   assert(AnOpts.UserMode == "shallow" || AnOpts.UserMode == "deep");
1253145449b1SDimitry Andric   const bool InShallowMode = AnOpts.UserMode == "shallow";
1254145449b1SDimitry Andric 
1255145449b1SDimitry Andric #define ANALYZER_OPTION(...)
1256676fbe81SDimitry Andric #define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC,        \
1257676fbe81SDimitry Andric                                              SHALLOW_VAL, DEEP_VAL)            \
1258145449b1SDimitry Andric   initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG,                       \
1259145449b1SDimitry Andric              InShallowMode ? SHALLOW_VAL : DEEP_VAL);
1260676fbe81SDimitry Andric #include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
1261676fbe81SDimitry Andric 
1262676fbe81SDimitry Andric   // At this point, AnalyzerOptions is configured. Let's validate some options.
1263676fbe81SDimitry Andric 
1264519fc96cSDimitry Andric   // FIXME: Here we try to validate the silenced checkers or packages are valid.
1265519fc96cSDimitry Andric   // The current approach only validates the registered checkers which does not
1266519fc96cSDimitry Andric   // contain the runtime enabled checkers and optimally we would validate both.
1267519fc96cSDimitry Andric   if (!AnOpts.RawSilencedCheckersAndPackages.empty()) {
1268519fc96cSDimitry Andric     std::vector<StringRef> Checkers =
1269519fc96cSDimitry Andric         AnOpts.getRegisteredCheckers(/*IncludeExperimental=*/true);
1270519fc96cSDimitry Andric     std::vector<StringRef> Packages =
1271519fc96cSDimitry Andric         AnOpts.getRegisteredPackages(/*IncludeExperimental=*/true);
1272519fc96cSDimitry Andric 
1273519fc96cSDimitry Andric     SmallVector<StringRef, 16> CheckersAndPackages;
1274519fc96cSDimitry Andric     AnOpts.RawSilencedCheckersAndPackages.split(CheckersAndPackages, ";");
1275519fc96cSDimitry Andric 
1276706b4fc4SDimitry Andric     for (const StringRef &CheckerOrPackage : CheckersAndPackages) {
1277519fc96cSDimitry Andric       if (Diags) {
1278519fc96cSDimitry Andric         bool IsChecker = CheckerOrPackage.contains('.');
1279c0981da4SDimitry Andric         bool IsValidName = IsChecker
1280c0981da4SDimitry Andric                                ? llvm::is_contained(Checkers, CheckerOrPackage)
1281c0981da4SDimitry Andric                                : llvm::is_contained(Packages, CheckerOrPackage);
1282519fc96cSDimitry Andric 
1283519fc96cSDimitry Andric         if (!IsValidName)
1284519fc96cSDimitry Andric           Diags->Report(diag::err_unknown_analyzer_checker_or_package)
1285519fc96cSDimitry Andric               << CheckerOrPackage;
1286519fc96cSDimitry Andric       }
1287519fc96cSDimitry Andric 
1288519fc96cSDimitry Andric       AnOpts.SilencedCheckersAndPackages.emplace_back(CheckerOrPackage);
1289519fc96cSDimitry Andric     }
1290519fc96cSDimitry Andric   }
1291519fc96cSDimitry Andric 
1292676fbe81SDimitry Andric   if (!Diags)
1293676fbe81SDimitry Andric     return;
1294676fbe81SDimitry Andric 
129522989816SDimitry Andric   if (AnOpts.ShouldTrackConditionsDebug && !AnOpts.ShouldTrackConditions)
129622989816SDimitry Andric     Diags->Report(diag::err_analyzer_config_invalid_input)
129722989816SDimitry Andric         << "track-conditions-debug" << "'track-conditions' to also be enabled";
129822989816SDimitry Andric 
1299676fbe81SDimitry Andric   if (!AnOpts.CTUDir.empty() && !llvm::sys::fs::is_directory(AnOpts.CTUDir))
1300676fbe81SDimitry Andric     Diags->Report(diag::err_analyzer_config_invalid_input) << "ctu-dir"
1301676fbe81SDimitry Andric                                                            << "a filename";
1302676fbe81SDimitry Andric 
1303676fbe81SDimitry Andric   if (!AnOpts.ModelPath.empty() &&
1304676fbe81SDimitry Andric       !llvm::sys::fs::is_directory(AnOpts.ModelPath))
1305676fbe81SDimitry Andric     Diags->Report(diag::err_analyzer_config_invalid_input) << "model-path"
1306676fbe81SDimitry Andric                                                            << "a filename";
1307676fbe81SDimitry Andric }
1308676fbe81SDimitry Andric 
1309344a3780SDimitry Andric /// Generate a remark argument. This is an inverse of `ParseOptimizationRemark`.
1310344a3780SDimitry Andric static void
GenerateOptimizationRemark(ArgumentConsumer Consumer,OptSpecifier OptEQ,StringRef Name,const CodeGenOptions::OptRemark & Remark)1311b1c73532SDimitry Andric GenerateOptimizationRemark(ArgumentConsumer Consumer, OptSpecifier OptEQ,
1312b1c73532SDimitry Andric                            StringRef Name,
1313344a3780SDimitry Andric                            const CodeGenOptions::OptRemark &Remark) {
1314344a3780SDimitry Andric   if (Remark.hasValidPattern()) {
1315b1c73532SDimitry Andric     GenerateArg(Consumer, OptEQ, Remark.Pattern);
1316344a3780SDimitry Andric   } else if (Remark.Kind == CodeGenOptions::RK_Enabled) {
1317b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_R_Joined, Name);
1318344a3780SDimitry Andric   } else if (Remark.Kind == CodeGenOptions::RK_Disabled) {
1319b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_R_Joined, StringRef("no-") + Name);
13209f4dbff6SDimitry Andric   }
1321344a3780SDimitry Andric }
1322344a3780SDimitry Andric 
1323344a3780SDimitry Andric /// Parse a remark command line argument. It may be missing, disabled/enabled by
1324344a3780SDimitry Andric /// '-R[no-]group' or specified with a regular expression by '-Rgroup=regexp'.
1325344a3780SDimitry Andric /// On top of that, it can be disabled/enabled globally by '-R[no-]everything'.
1326344a3780SDimitry Andric static CodeGenOptions::OptRemark
ParseOptimizationRemark(DiagnosticsEngine & Diags,ArgList & Args,OptSpecifier OptEQ,StringRef Name)1327344a3780SDimitry Andric ParseOptimizationRemark(DiagnosticsEngine &Diags, ArgList &Args,
1328344a3780SDimitry Andric                         OptSpecifier OptEQ, StringRef Name) {
1329344a3780SDimitry Andric   CodeGenOptions::OptRemark Result;
1330344a3780SDimitry Andric 
1331c0981da4SDimitry Andric   auto InitializeResultPattern = [&Diags, &Args, &Result](const Arg *A,
1332c0981da4SDimitry Andric                                                           StringRef Pattern) {
1333c0981da4SDimitry Andric     Result.Pattern = Pattern.str();
1334344a3780SDimitry Andric 
1335344a3780SDimitry Andric     std::string RegexError;
1336344a3780SDimitry Andric     Result.Regex = std::make_shared<llvm::Regex>(Result.Pattern);
1337344a3780SDimitry Andric     if (!Result.Regex->isValid(RegexError)) {
1338344a3780SDimitry Andric       Diags.Report(diag::err_drv_optimization_remark_pattern)
1339344a3780SDimitry Andric           << RegexError << A->getAsString(Args);
1340344a3780SDimitry Andric       return false;
1341344a3780SDimitry Andric     }
1342344a3780SDimitry Andric 
1343344a3780SDimitry Andric     return true;
1344344a3780SDimitry Andric   };
1345344a3780SDimitry Andric 
1346344a3780SDimitry Andric   for (Arg *A : Args) {
1347344a3780SDimitry Andric     if (A->getOption().matches(OPT_R_Joined)) {
1348344a3780SDimitry Andric       StringRef Value = A->getValue();
1349344a3780SDimitry Andric 
1350344a3780SDimitry Andric       if (Value == Name)
1351344a3780SDimitry Andric         Result.Kind = CodeGenOptions::RK_Enabled;
1352344a3780SDimitry Andric       else if (Value == "everything")
1353344a3780SDimitry Andric         Result.Kind = CodeGenOptions::RK_EnabledEverything;
1354344a3780SDimitry Andric       else if (Value.split('-') == std::make_pair(StringRef("no"), Name))
1355344a3780SDimitry Andric         Result.Kind = CodeGenOptions::RK_Disabled;
1356344a3780SDimitry Andric       else if (Value == "no-everything")
1357344a3780SDimitry Andric         Result.Kind = CodeGenOptions::RK_DisabledEverything;
1358c0981da4SDimitry Andric       else
1359c0981da4SDimitry Andric         continue;
1360344a3780SDimitry Andric 
1361344a3780SDimitry Andric       if (Result.Kind == CodeGenOptions::RK_Disabled ||
1362344a3780SDimitry Andric           Result.Kind == CodeGenOptions::RK_DisabledEverything) {
1363344a3780SDimitry Andric         Result.Pattern = "";
1364344a3780SDimitry Andric         Result.Regex = nullptr;
1365c0981da4SDimitry Andric       } else {
1366c0981da4SDimitry Andric         InitializeResultPattern(A, ".*");
1367c0981da4SDimitry Andric       }
1368c0981da4SDimitry Andric     } else if (A->getOption().matches(OptEQ)) {
1369c0981da4SDimitry Andric       Result.Kind = CodeGenOptions::RK_WithPattern;
1370c0981da4SDimitry Andric       if (!InitializeResultPattern(A, A->getValue()))
1371c0981da4SDimitry Andric         return CodeGenOptions::OptRemark();
1372c0981da4SDimitry Andric     }
1373344a3780SDimitry Andric   }
1374344a3780SDimitry Andric 
1375344a3780SDimitry Andric   return Result;
13769f4dbff6SDimitry Andric }
13779f4dbff6SDimitry Andric 
parseDiagnosticLevelMask(StringRef FlagName,const std::vector<std::string> & Levels,DiagnosticsEngine & Diags,DiagnosticLevelMask & M)13782e645aa5SDimitry Andric static bool parseDiagnosticLevelMask(StringRef FlagName,
13792e645aa5SDimitry Andric                                      const std::vector<std::string> &Levels,
1380b60736ecSDimitry Andric                                      DiagnosticsEngine &Diags,
13812e645aa5SDimitry Andric                                      DiagnosticLevelMask &M) {
13822e645aa5SDimitry Andric   bool Success = true;
13832e645aa5SDimitry Andric   for (const auto &Level : Levels) {
13842e645aa5SDimitry Andric     DiagnosticLevelMask const PM =
13852e645aa5SDimitry Andric       llvm::StringSwitch<DiagnosticLevelMask>(Level)
13862e645aa5SDimitry Andric         .Case("note",    DiagnosticLevelMask::Note)
13872e645aa5SDimitry Andric         .Case("remark",  DiagnosticLevelMask::Remark)
13882e645aa5SDimitry Andric         .Case("warning", DiagnosticLevelMask::Warning)
13892e645aa5SDimitry Andric         .Case("error",   DiagnosticLevelMask::Error)
13902e645aa5SDimitry Andric         .Default(DiagnosticLevelMask::None);
13912e645aa5SDimitry Andric     if (PM == DiagnosticLevelMask::None) {
13922e645aa5SDimitry Andric       Success = false;
1393b60736ecSDimitry Andric       Diags.Report(diag::err_drv_invalid_value) << FlagName << Level;
13942e645aa5SDimitry Andric     }
13952e645aa5SDimitry Andric     M = M | PM;
13962e645aa5SDimitry Andric   }
13972e645aa5SDimitry Andric   return Success;
13982e645aa5SDimitry Andric }
13992e645aa5SDimitry Andric 
parseSanitizerKinds(StringRef FlagName,const std::vector<std::string> & Sanitizers,DiagnosticsEngine & Diags,SanitizerSet & S)140006d4ba38SDimitry Andric static void parseSanitizerKinds(StringRef FlagName,
140106d4ba38SDimitry Andric                                 const std::vector<std::string> &Sanitizers,
140206d4ba38SDimitry Andric                                 DiagnosticsEngine &Diags, SanitizerSet &S) {
140306d4ba38SDimitry Andric   for (const auto &Sanitizer : Sanitizers) {
14045e20cdd8SDimitry Andric     SanitizerMask K = parseSanitizerValue(Sanitizer, /*AllowGroups=*/false);
140522989816SDimitry Andric     if (K == SanitizerMask())
140606d4ba38SDimitry Andric       Diags.Report(diag::err_drv_invalid_value) << FlagName << Sanitizer;
140706d4ba38SDimitry Andric     else
140806d4ba38SDimitry Andric       S.set(K, true);
140906d4ba38SDimitry Andric   }
141006d4ba38SDimitry Andric }
141106d4ba38SDimitry Andric 
serializeSanitizerKinds(SanitizerSet S)1412344a3780SDimitry Andric static SmallVector<StringRef, 4> serializeSanitizerKinds(SanitizerSet S) {
1413344a3780SDimitry Andric   SmallVector<StringRef, 4> Values;
1414344a3780SDimitry Andric   serializeSanitizerSet(S, Values);
1415344a3780SDimitry Andric   return Values;
1416344a3780SDimitry Andric }
1417344a3780SDimitry Andric 
parseXRayInstrumentationBundle(StringRef FlagName,StringRef Bundle,ArgList & Args,DiagnosticsEngine & D,XRayInstrSet & S)141848675466SDimitry Andric static void parseXRayInstrumentationBundle(StringRef FlagName, StringRef Bundle,
141948675466SDimitry Andric                                            ArgList &Args, DiagnosticsEngine &D,
142048675466SDimitry Andric                                            XRayInstrSet &S) {
142148675466SDimitry Andric   llvm::SmallVector<StringRef, 2> BundleParts;
142248675466SDimitry Andric   llvm::SplitString(Bundle, BundleParts, ",");
1423706b4fc4SDimitry Andric   for (const auto &B : BundleParts) {
142448675466SDimitry Andric     auto Mask = parseXRayInstrValue(B);
142548675466SDimitry Andric     if (Mask == XRayInstrKind::None)
142648675466SDimitry Andric       if (B != "none")
142748675466SDimitry Andric         D.Report(diag::err_drv_invalid_value) << FlagName << Bundle;
142848675466SDimitry Andric       else
142948675466SDimitry Andric         S.Mask = Mask;
143048675466SDimitry Andric     else if (Mask == XRayInstrKind::All)
143148675466SDimitry Andric       S.Mask = Mask;
143248675466SDimitry Andric     else
143348675466SDimitry Andric       S.set(Mask, true);
143448675466SDimitry Andric   }
143548675466SDimitry Andric }
143648675466SDimitry Andric 
serializeXRayInstrumentationBundle(const XRayInstrSet & S)1437344a3780SDimitry Andric static std::string serializeXRayInstrumentationBundle(const XRayInstrSet &S) {
1438344a3780SDimitry Andric   llvm::SmallVector<StringRef, 2> BundleParts;
1439344a3780SDimitry Andric   serializeXRayInstrValue(S, BundleParts);
1440344a3780SDimitry Andric   std::string Buffer;
1441344a3780SDimitry Andric   llvm::raw_string_ostream OS(Buffer);
1442344a3780SDimitry Andric   llvm::interleave(BundleParts, OS, [&OS](StringRef Part) { OS << Part; }, ",");
144377fc4c14SDimitry Andric   return Buffer;
1444344a3780SDimitry Andric }
1445344a3780SDimitry Andric 
14462b6b257fSDimitry Andric // Set the profile kind using fprofile-instrument-use-path.
setPGOUseInstrumentor(CodeGenOptions & Opts,const Twine & ProfileName,llvm::vfs::FileSystem & FS,DiagnosticsEngine & Diags)14472b6b257fSDimitry Andric static void setPGOUseInstrumentor(CodeGenOptions &Opts,
1448e3b55780SDimitry Andric                                   const Twine &ProfileName,
14497fa27ce4SDimitry Andric                                   llvm::vfs::FileSystem &FS,
1450e3b55780SDimitry Andric                                   DiagnosticsEngine &Diags) {
14517fa27ce4SDimitry Andric   auto ReaderOrErr = llvm::IndexedInstrProfReader::create(ProfileName, FS);
14522b6b257fSDimitry Andric   if (auto E = ReaderOrErr.takeError()) {
1453e3b55780SDimitry Andric     unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
1454e3b55780SDimitry Andric                                             "Error in reading profile %0: %1");
1455e3b55780SDimitry Andric     llvm::handleAllErrors(std::move(E), [&](const llvm::ErrorInfoBase &EI) {
1456e3b55780SDimitry Andric       Diags.Report(DiagID) << ProfileName.str() << EI.message();
1457e3b55780SDimitry Andric     });
14582b6b257fSDimitry Andric     return;
14592b6b257fSDimitry Andric   }
14602b6b257fSDimitry Andric   std::unique_ptr<llvm::IndexedInstrProfReader> PGOReader =
14612b6b257fSDimitry Andric     std::move(ReaderOrErr.get());
1462e3b55780SDimitry Andric   // Currently memprof profiles are only added at the IR level. Mark the profile
1463e3b55780SDimitry Andric   // type as IR in that case as well and the subsequent matching needs to detect
1464e3b55780SDimitry Andric   // which is available (might be one or both).
1465e3b55780SDimitry Andric   if (PGOReader->isIRLevelProfile() || PGOReader->hasMemoryProfile()) {
146622989816SDimitry Andric     if (PGOReader->hasCSIRLevelProfile())
146722989816SDimitry Andric       Opts.setProfileUse(CodeGenOptions::ProfileCSIRInstr);
14682b6b257fSDimitry Andric     else
146922989816SDimitry Andric       Opts.setProfileUse(CodeGenOptions::ProfileIRInstr);
147022989816SDimitry Andric   } else
14712b6b257fSDimitry Andric     Opts.setProfileUse(CodeGenOptions::ProfileClangInstr);
14722b6b257fSDimitry Andric }
14732b6b257fSDimitry Andric 
setDefaultPointerAuthOptions(PointerAuthOptions & Opts,const LangOptions & LangOpts,const llvm::Triple & Triple)1474ac9a064cSDimitry Andric void CompilerInvocation::setDefaultPointerAuthOptions(
1475ac9a064cSDimitry Andric     PointerAuthOptions &Opts, const LangOptions &LangOpts,
1476ac9a064cSDimitry Andric     const llvm::Triple &Triple) {
1477ac9a064cSDimitry Andric   assert(Triple.getArch() == llvm::Triple::aarch64);
1478ac9a064cSDimitry Andric   if (LangOpts.PointerAuthCalls) {
1479ac9a064cSDimitry Andric     using Key = PointerAuthSchema::ARM8_3Key;
1480ac9a064cSDimitry Andric     using Discrimination = PointerAuthSchema::Discrimination;
1481ac9a064cSDimitry Andric     // If you change anything here, be sure to update <ptrauth.h>.
1482ac9a064cSDimitry Andric     Opts.FunctionPointers = PointerAuthSchema(
1483ac9a064cSDimitry Andric         Key::ASIA, false,
1484ac9a064cSDimitry Andric         LangOpts.PointerAuthFunctionTypeDiscrimination ? Discrimination::Type
1485ac9a064cSDimitry Andric                                                        : Discrimination::None);
1486ac9a064cSDimitry Andric 
1487ac9a064cSDimitry Andric     Opts.CXXVTablePointers = PointerAuthSchema(
1488ac9a064cSDimitry Andric         Key::ASDA, LangOpts.PointerAuthVTPtrAddressDiscrimination,
1489ac9a064cSDimitry Andric         LangOpts.PointerAuthVTPtrTypeDiscrimination ? Discrimination::Type
1490ac9a064cSDimitry Andric                                                     : Discrimination::None);
1491ac9a064cSDimitry Andric 
1492ac9a064cSDimitry Andric     if (LangOpts.PointerAuthTypeInfoVTPtrDiscrimination)
1493ac9a064cSDimitry Andric       Opts.CXXTypeInfoVTablePointer =
1494ac9a064cSDimitry Andric           PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,
1495ac9a064cSDimitry Andric                             StdTypeInfoVTablePointerConstantDiscrimination);
1496ac9a064cSDimitry Andric     else
1497ac9a064cSDimitry Andric       Opts.CXXTypeInfoVTablePointer =
1498ac9a064cSDimitry Andric           PointerAuthSchema(Key::ASDA, false, Discrimination::None);
1499ac9a064cSDimitry Andric 
1500ac9a064cSDimitry Andric     Opts.CXXVTTVTablePointers =
1501ac9a064cSDimitry Andric         PointerAuthSchema(Key::ASDA, false, Discrimination::None);
1502ac9a064cSDimitry Andric     Opts.CXXVirtualFunctionPointers = Opts.CXXVirtualVariadicFunctionPointers =
1503ac9a064cSDimitry Andric         PointerAuthSchema(Key::ASIA, true, Discrimination::Decl);
1504ac9a064cSDimitry Andric     Opts.CXXMemberFunctionPointers =
1505ac9a064cSDimitry Andric         PointerAuthSchema(Key::ASIA, false, Discrimination::Type);
1506ac9a064cSDimitry Andric   }
1507adf62863SDimitry Andric   Opts.ReturnAddresses = LangOpts.PointerAuthReturns;
1508adf62863SDimitry Andric   Opts.AuthTraps = LangOpts.PointerAuthAuthTraps;
1509ac9a064cSDimitry Andric   Opts.IndirectGotos = LangOpts.PointerAuthIndirectGotos;
1510ac9a064cSDimitry Andric }
1511ac9a064cSDimitry Andric 
parsePointerAuthOptions(PointerAuthOptions & Opts,const LangOptions & LangOpts,const llvm::Triple & Triple,DiagnosticsEngine & Diags)1512ac9a064cSDimitry Andric static void parsePointerAuthOptions(PointerAuthOptions &Opts,
1513ac9a064cSDimitry Andric                                     const LangOptions &LangOpts,
1514ac9a064cSDimitry Andric                                     const llvm::Triple &Triple,
1515ac9a064cSDimitry Andric                                     DiagnosticsEngine &Diags) {
1516adf62863SDimitry Andric   if (!LangOpts.PointerAuthCalls && !LangOpts.PointerAuthReturns &&
1517adf62863SDimitry Andric       !LangOpts.PointerAuthAuthTraps && !LangOpts.PointerAuthIndirectGotos)
1518ac9a064cSDimitry Andric     return;
1519ac9a064cSDimitry Andric 
1520ac9a064cSDimitry Andric   CompilerInvocation::setDefaultPointerAuthOptions(Opts, LangOpts, Triple);
1521ac9a064cSDimitry Andric }
1522ac9a064cSDimitry Andric 
GenerateCodeGenArgs(const CodeGenOptions & Opts,ArgumentConsumer Consumer,const llvm::Triple & T,const std::string & OutputFile,const LangOptions * LangOpts)1523b1c73532SDimitry Andric void CompilerInvocationBase::GenerateCodeGenArgs(const CodeGenOptions &Opts,
1524b1c73532SDimitry Andric                                                  ArgumentConsumer Consumer,
1525b1c73532SDimitry Andric                                                  const llvm::Triple &T,
1526b1c73532SDimitry Andric                                                  const std::string &OutputFile,
1527344a3780SDimitry Andric                                                  const LangOptions *LangOpts) {
1528344a3780SDimitry Andric   const CodeGenOptions &CodeGenOpts = Opts;
1529344a3780SDimitry Andric 
1530344a3780SDimitry Andric   if (Opts.OptimizationLevel == 0)
1531b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_O0);
1532344a3780SDimitry Andric   else
1533b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_O, Twine(Opts.OptimizationLevel));
1534344a3780SDimitry Andric 
15357fa27ce4SDimitry Andric #define CODEGEN_OPTION_WITH_MARSHALLING(...)                                   \
1536b1c73532SDimitry Andric   GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
1537344a3780SDimitry Andric #include "clang/Driver/Options.inc"
1538344a3780SDimitry Andric #undef CODEGEN_OPTION_WITH_MARSHALLING
1539344a3780SDimitry Andric 
1540344a3780SDimitry Andric   if (Opts.OptimizationLevel > 0) {
1541344a3780SDimitry Andric     if (Opts.Inlining == CodeGenOptions::NormalInlining)
1542b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_finline_functions);
1543344a3780SDimitry Andric     else if (Opts.Inlining == CodeGenOptions::OnlyHintInlining)
1544b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_finline_hint_functions);
1545344a3780SDimitry Andric     else if (Opts.Inlining == CodeGenOptions::OnlyAlwaysInlining)
1546b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_fno_inline);
1547344a3780SDimitry Andric   }
1548344a3780SDimitry Andric 
1549344a3780SDimitry Andric   if (Opts.DirectAccessExternalData && LangOpts->PICLevel != 0)
1550b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fdirect_access_external_data);
1551344a3780SDimitry Andric   else if (!Opts.DirectAccessExternalData && LangOpts->PICLevel == 0)
1552b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fno_direct_access_external_data);
1553344a3780SDimitry Andric 
1554e3b55780SDimitry Andric   std::optional<StringRef> DebugInfoVal;
1555344a3780SDimitry Andric   switch (Opts.DebugInfo) {
15567fa27ce4SDimitry Andric   case llvm::codegenoptions::DebugLineTablesOnly:
1557344a3780SDimitry Andric     DebugInfoVal = "line-tables-only";
1558344a3780SDimitry Andric     break;
15597fa27ce4SDimitry Andric   case llvm::codegenoptions::DebugDirectivesOnly:
1560344a3780SDimitry Andric     DebugInfoVal = "line-directives-only";
1561344a3780SDimitry Andric     break;
15627fa27ce4SDimitry Andric   case llvm::codegenoptions::DebugInfoConstructor:
1563344a3780SDimitry Andric     DebugInfoVal = "constructor";
1564344a3780SDimitry Andric     break;
15657fa27ce4SDimitry Andric   case llvm::codegenoptions::LimitedDebugInfo:
1566344a3780SDimitry Andric     DebugInfoVal = "limited";
1567344a3780SDimitry Andric     break;
15687fa27ce4SDimitry Andric   case llvm::codegenoptions::FullDebugInfo:
1569344a3780SDimitry Andric     DebugInfoVal = "standalone";
1570344a3780SDimitry Andric     break;
15717fa27ce4SDimitry Andric   case llvm::codegenoptions::UnusedTypeInfo:
1572344a3780SDimitry Andric     DebugInfoVal = "unused-types";
1573344a3780SDimitry Andric     break;
15747fa27ce4SDimitry Andric   case llvm::codegenoptions::NoDebugInfo: // default value
1575e3b55780SDimitry Andric     DebugInfoVal = std::nullopt;
1576344a3780SDimitry Andric     break;
15777fa27ce4SDimitry Andric   case llvm::codegenoptions::LocTrackingOnly: // implied value
1578e3b55780SDimitry Andric     DebugInfoVal = std::nullopt;
1579344a3780SDimitry Andric     break;
1580344a3780SDimitry Andric   }
1581344a3780SDimitry Andric   if (DebugInfoVal)
1582b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_debug_info_kind_EQ, *DebugInfoVal);
1583344a3780SDimitry Andric 
1584344a3780SDimitry Andric   for (const auto &Prefix : Opts.DebugPrefixMap)
1585b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fdebug_prefix_map_EQ,
1586b1c73532SDimitry Andric                 Prefix.first + "=" + Prefix.second);
1587344a3780SDimitry Andric 
1588344a3780SDimitry Andric   for (const auto &Prefix : Opts.CoveragePrefixMap)
1589b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fcoverage_prefix_map_EQ,
1590b1c73532SDimitry Andric                 Prefix.first + "=" + Prefix.second);
1591344a3780SDimitry Andric 
1592344a3780SDimitry Andric   if (Opts.NewStructPathTBAA)
1593b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_new_struct_path_tbaa);
1594344a3780SDimitry Andric 
1595344a3780SDimitry Andric   if (Opts.OptimizeSize == 1)
1596b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_O, "s");
1597344a3780SDimitry Andric   else if (Opts.OptimizeSize == 2)
1598b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_O, "z");
1599344a3780SDimitry Andric 
1600344a3780SDimitry Andric   // SimplifyLibCalls is set only in the absence of -fno-builtin and
1601344a3780SDimitry Andric   // -ffreestanding. We'll consider that when generating them.
1602344a3780SDimitry Andric 
1603344a3780SDimitry Andric   // NoBuiltinFuncs are generated by LangOptions.
1604344a3780SDimitry Andric 
1605344a3780SDimitry Andric   if (Opts.UnrollLoops && Opts.OptimizationLevel <= 1)
1606b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_funroll_loops);
1607344a3780SDimitry Andric   else if (!Opts.UnrollLoops && Opts.OptimizationLevel > 1)
1608b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fno_unroll_loops);
1609344a3780SDimitry Andric 
1610344a3780SDimitry Andric   if (!Opts.BinutilsVersion.empty())
1611b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fbinutils_version_EQ, Opts.BinutilsVersion);
1612344a3780SDimitry Andric 
1613344a3780SDimitry Andric   if (Opts.DebugNameTable ==
1614344a3780SDimitry Andric       static_cast<unsigned>(llvm::DICompileUnit::DebugNameTableKind::GNU))
1615b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_ggnu_pubnames);
1616344a3780SDimitry Andric   else if (Opts.DebugNameTable ==
1617344a3780SDimitry Andric            static_cast<unsigned>(
1618344a3780SDimitry Andric                llvm::DICompileUnit::DebugNameTableKind::Default))
1619b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_gpubnames);
1620344a3780SDimitry Andric 
1621ac9a064cSDimitry Andric   if (Opts.DebugTemplateAlias)
1622ac9a064cSDimitry Andric     GenerateArg(Consumer, OPT_gtemplate_alias);
1623ac9a064cSDimitry Andric 
1624c0981da4SDimitry Andric   auto TNK = Opts.getDebugSimpleTemplateNames();
16257fa27ce4SDimitry Andric   if (TNK != llvm::codegenoptions::DebugTemplateNamesKind::Full) {
16267fa27ce4SDimitry Andric     if (TNK == llvm::codegenoptions::DebugTemplateNamesKind::Simple)
1627b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_gsimple_template_names_EQ, "simple");
16287fa27ce4SDimitry Andric     else if (TNK == llvm::codegenoptions::DebugTemplateNamesKind::Mangled)
1629b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_gsimple_template_names_EQ, "mangled");
1630c0981da4SDimitry Andric   }
1631344a3780SDimitry Andric   // ProfileInstrumentUsePath is marshalled automatically, no need to generate
1632344a3780SDimitry Andric   // it or PGOUseInstrumentor.
1633344a3780SDimitry Andric 
1634344a3780SDimitry Andric   if (Opts.TimePasses) {
1635344a3780SDimitry Andric     if (Opts.TimePassesPerRun)
1636b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_ftime_report_EQ, "per-pass-run");
1637344a3780SDimitry Andric     else
1638b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_ftime_report);
1639344a3780SDimitry Andric   }
1640344a3780SDimitry Andric 
1641344a3780SDimitry Andric   if (Opts.PrepareForLTO && !Opts.PrepareForThinLTO)
1642b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_flto_EQ, "full");
1643344a3780SDimitry Andric 
1644344a3780SDimitry Andric   if (Opts.PrepareForThinLTO)
1645b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_flto_EQ, "thin");
1646344a3780SDimitry Andric 
1647344a3780SDimitry Andric   if (!Opts.ThinLTOIndexFile.empty())
1648b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fthinlto_index_EQ, Opts.ThinLTOIndexFile);
1649344a3780SDimitry Andric 
1650344a3780SDimitry Andric   if (Opts.SaveTempsFilePrefix == OutputFile)
1651b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_save_temps_EQ, "obj");
1652344a3780SDimitry Andric 
1653344a3780SDimitry Andric   StringRef MemProfileBasename("memprof.profraw");
1654344a3780SDimitry Andric   if (!Opts.MemoryProfileOutput.empty()) {
1655344a3780SDimitry Andric     if (Opts.MemoryProfileOutput == MemProfileBasename) {
1656b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_fmemory_profile);
1657344a3780SDimitry Andric     } else {
1658344a3780SDimitry Andric       size_t ArgLength =
1659344a3780SDimitry Andric           Opts.MemoryProfileOutput.size() - MemProfileBasename.size();
1660b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_fmemory_profile_EQ,
1661b1c73532SDimitry Andric                   Opts.MemoryProfileOutput.substr(0, ArgLength));
1662344a3780SDimitry Andric     }
1663344a3780SDimitry Andric   }
1664344a3780SDimitry Andric 
1665344a3780SDimitry Andric   if (memcmp(Opts.CoverageVersion, "408*", 4) != 0)
1666b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_coverage_version_EQ,
1667b1c73532SDimitry Andric                 StringRef(Opts.CoverageVersion, 4));
1668344a3780SDimitry Andric 
1669344a3780SDimitry Andric   // TODO: Check if we need to generate arguments stored in CmdArgs. (Namely
1670344a3780SDimitry Andric   //  '-fembed_bitcode', which does not map to any CompilerInvocation field and
1671344a3780SDimitry Andric   //  won't be generated.)
1672344a3780SDimitry Andric 
1673344a3780SDimitry Andric   if (Opts.XRayInstrumentationBundle.Mask != XRayInstrKind::All) {
1674344a3780SDimitry Andric     std::string InstrBundle =
1675344a3780SDimitry Andric         serializeXRayInstrumentationBundle(Opts.XRayInstrumentationBundle);
1676344a3780SDimitry Andric     if (!InstrBundle.empty())
1677b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_fxray_instrumentation_bundle, InstrBundle);
1678344a3780SDimitry Andric   }
1679344a3780SDimitry Andric 
1680344a3780SDimitry Andric   if (Opts.CFProtectionReturn && Opts.CFProtectionBranch)
1681b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fcf_protection_EQ, "full");
1682344a3780SDimitry Andric   else if (Opts.CFProtectionReturn)
1683b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fcf_protection_EQ, "return");
1684344a3780SDimitry Andric   else if (Opts.CFProtectionBranch)
1685b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fcf_protection_EQ, "branch");
1686344a3780SDimitry Andric 
16871f917f69SDimitry Andric   if (Opts.FunctionReturnThunks)
1688b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_mfunction_return_EQ, "thunk-extern");
16891f917f69SDimitry Andric 
1690344a3780SDimitry Andric   for (const auto &F : Opts.LinkBitcodeFiles) {
1691344a3780SDimitry Andric     bool Builtint = F.LinkFlags == llvm::Linker::Flags::LinkOnlyNeeded &&
1692344a3780SDimitry Andric                     F.PropagateAttrs && F.Internalize;
1693b1c73532SDimitry Andric     GenerateArg(Consumer,
1694344a3780SDimitry Andric                 Builtint ? OPT_mlink_builtin_bitcode : OPT_mlink_bitcode_file,
1695b1c73532SDimitry Andric                 F.Filename);
1696344a3780SDimitry Andric   }
1697344a3780SDimitry Andric 
16987fa27ce4SDimitry Andric   if (Opts.EmulatedTLS)
1699b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_femulated_tls);
1700344a3780SDimitry Andric 
1701344a3780SDimitry Andric   if (Opts.FPDenormalMode != llvm::DenormalMode::getIEEE())
1702b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fdenormal_fp_math_EQ, Opts.FPDenormalMode.str());
1703344a3780SDimitry Andric 
1704145449b1SDimitry Andric   if ((Opts.FPDenormalMode != Opts.FP32DenormalMode) ||
1705145449b1SDimitry Andric       (Opts.FP32DenormalMode != llvm::DenormalMode::getIEEE()))
1706b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fdenormal_fp_math_f32_EQ,
1707b1c73532SDimitry Andric                 Opts.FP32DenormalMode.str());
1708344a3780SDimitry Andric 
1709344a3780SDimitry Andric   if (Opts.StructReturnConvention == CodeGenOptions::SRCK_OnStack) {
1710344a3780SDimitry Andric     OptSpecifier Opt =
1711344a3780SDimitry Andric         T.isPPC32() ? OPT_maix_struct_return : OPT_fpcc_struct_return;
1712b1c73532SDimitry Andric     GenerateArg(Consumer, Opt);
1713344a3780SDimitry Andric   } else if (Opts.StructReturnConvention == CodeGenOptions::SRCK_InRegs) {
1714344a3780SDimitry Andric     OptSpecifier Opt =
1715344a3780SDimitry Andric         T.isPPC32() ? OPT_msvr4_struct_return : OPT_freg_struct_return;
1716b1c73532SDimitry Andric     GenerateArg(Consumer, Opt);
1717344a3780SDimitry Andric   }
1718344a3780SDimitry Andric 
1719344a3780SDimitry Andric   if (Opts.EnableAIXExtendedAltivecABI)
1720b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_mabi_EQ_vec_extabi);
1721344a3780SDimitry Andric 
17227fa27ce4SDimitry Andric   if (Opts.XCOFFReadOnlyPointers)
1723b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_mxcoff_roptr);
17247fa27ce4SDimitry Andric 
1725344a3780SDimitry Andric   if (!Opts.OptRecordPasses.empty())
1726b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_opt_record_passes, Opts.OptRecordPasses);
1727344a3780SDimitry Andric 
1728344a3780SDimitry Andric   if (!Opts.OptRecordFormat.empty())
1729b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_opt_record_format, Opts.OptRecordFormat);
1730344a3780SDimitry Andric 
1731b1c73532SDimitry Andric   GenerateOptimizationRemark(Consumer, OPT_Rpass_EQ, "pass",
1732344a3780SDimitry Andric                              Opts.OptimizationRemark);
1733344a3780SDimitry Andric 
1734b1c73532SDimitry Andric   GenerateOptimizationRemark(Consumer, OPT_Rpass_missed_EQ, "pass-missed",
1735344a3780SDimitry Andric                              Opts.OptimizationRemarkMissed);
1736344a3780SDimitry Andric 
1737b1c73532SDimitry Andric   GenerateOptimizationRemark(Consumer, OPT_Rpass_analysis_EQ, "pass-analysis",
1738344a3780SDimitry Andric                              Opts.OptimizationRemarkAnalysis);
1739344a3780SDimitry Andric 
1740b1c73532SDimitry Andric   GenerateArg(Consumer, OPT_fdiagnostics_hotness_threshold_EQ,
1741344a3780SDimitry Andric               Opts.DiagnosticsHotnessThreshold
1742344a3780SDimitry Andric                   ? Twine(*Opts.DiagnosticsHotnessThreshold)
1743b1c73532SDimitry Andric                   : "auto");
1744344a3780SDimitry Andric 
1745b1c73532SDimitry Andric   GenerateArg(Consumer, OPT_fdiagnostics_misexpect_tolerance_EQ,
1746b1c73532SDimitry Andric               Twine(*Opts.DiagnosticsMisExpectTolerance));
1747145449b1SDimitry Andric 
1748344a3780SDimitry Andric   for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeRecover))
1749b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fsanitize_recover_EQ, Sanitizer);
1750344a3780SDimitry Andric 
1751344a3780SDimitry Andric   for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeTrap))
1752b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fsanitize_trap_EQ, Sanitizer);
1753344a3780SDimitry Andric 
1754344a3780SDimitry Andric   if (!Opts.EmitVersionIdentMetadata)
1755b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_Qn);
1756344a3780SDimitry Andric 
1757344a3780SDimitry Andric   switch (Opts.FiniteLoops) {
1758344a3780SDimitry Andric   case CodeGenOptions::FiniteLoopsKind::Language:
1759344a3780SDimitry Andric     break;
1760344a3780SDimitry Andric   case CodeGenOptions::FiniteLoopsKind::Always:
1761b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_ffinite_loops);
1762344a3780SDimitry Andric     break;
1763344a3780SDimitry Andric   case CodeGenOptions::FiniteLoopsKind::Never:
1764b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fno_finite_loops);
1765344a3780SDimitry Andric     break;
1766344a3780SDimitry Andric   }
1767344a3780SDimitry Andric }
1768344a3780SDimitry Andric 
ParseCodeGenArgs(CodeGenOptions & Opts,ArgList & Args,InputKind IK,DiagnosticsEngine & Diags,const llvm::Triple & T,const std::string & OutputFile,const LangOptions & LangOptsRef)1769b60736ecSDimitry Andric bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
1770b60736ecSDimitry Andric                                           InputKind IK,
17719f4dbff6SDimitry Andric                                           DiagnosticsEngine &Diags,
1772b60736ecSDimitry Andric                                           const llvm::Triple &T,
1773b60736ecSDimitry Andric                                           const std::string &OutputFile,
1774b60736ecSDimitry Andric                                           const LangOptions &LangOptsRef) {
1775344a3780SDimitry Andric   unsigned NumErrorsBefore = Diags.getNumErrors();
1776bca07a45SDimitry Andric 
177706d4ba38SDimitry Andric   unsigned OptimizationLevel = getOptimizationLevel(Args, IK, Diags);
1778bfef3995SDimitry Andric   // TODO: This could be done in Driver
1779bfef3995SDimitry Andric   unsigned MaxOptLevel = 3;
178006d4ba38SDimitry Andric   if (OptimizationLevel > MaxOptLevel) {
178106d4ba38SDimitry Andric     // If the optimization level is not supported, fall back on the default
178206d4ba38SDimitry Andric     // optimization
1783bfef3995SDimitry Andric     Diags.Report(diag::warn_drv_optimization_value)
1784bfef3995SDimitry Andric         << Args.getLastArg(OPT_O)->getAsString(Args) << "-O" << MaxOptLevel;
178506d4ba38SDimitry Andric     OptimizationLevel = MaxOptLevel;
17861569ce68SRoman Divacky   }
178706d4ba38SDimitry Andric   Opts.OptimizationLevel = OptimizationLevel;
17881569ce68SRoman Divacky 
1789b60736ecSDimitry Andric   // The key paths of codegen options defined in Options.td start with
1790b60736ecSDimitry Andric   // "CodeGenOpts.". Let's provide the expected variable name and type.
1791b60736ecSDimitry Andric   CodeGenOptions &CodeGenOpts = Opts;
1792b60736ecSDimitry Andric   // Some codegen options depend on language options. Let's provide the expected
1793b60736ecSDimitry Andric   // variable name and type.
1794b60736ecSDimitry Andric   const LangOptions *LangOpts = &LangOptsRef;
1795b60736ecSDimitry Andric 
17967fa27ce4SDimitry Andric #define CODEGEN_OPTION_WITH_MARSHALLING(...)                                   \
17977fa27ce4SDimitry Andric   PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
1798b60736ecSDimitry Andric #include "clang/Driver/Options.inc"
1799b60736ecSDimitry Andric #undef CODEGEN_OPTION_WITH_MARSHALLING
1800b60736ecSDimitry Andric 
1801bab175ecSDimitry Andric   // At O0 we want to fully disable inlining outside of cases marked with
1802bab175ecSDimitry Andric   // 'alwaysinline' that are required for correctness.
1803145449b1SDimitry Andric   if (Opts.OptimizationLevel == 0) {
1804145449b1SDimitry Andric     Opts.setInlining(CodeGenOptions::OnlyAlwaysInlining);
1805145449b1SDimitry Andric   } else if (const Arg *A = Args.getLastArg(options::OPT_finline_functions,
1806145449b1SDimitry Andric                                             options::OPT_finline_hint_functions,
1807145449b1SDimitry Andric                                             options::OPT_fno_inline_functions,
1808145449b1SDimitry Andric                                             options::OPT_fno_inline)) {
1809bab175ecSDimitry Andric     // Explicit inlining flags can disable some or all inlining even at
1810bab175ecSDimitry Andric     // optimization levels above zero.
1811145449b1SDimitry Andric     if (A->getOption().matches(options::OPT_finline_functions))
18122b6b257fSDimitry Andric       Opts.setInlining(CodeGenOptions::NormalInlining);
1813145449b1SDimitry Andric     else if (A->getOption().matches(options::OPT_finline_hint_functions))
18142b6b257fSDimitry Andric       Opts.setInlining(CodeGenOptions::OnlyHintInlining);
18152b6b257fSDimitry Andric     else
18162b6b257fSDimitry Andric       Opts.setInlining(CodeGenOptions::OnlyAlwaysInlining);
1817145449b1SDimitry Andric   } else {
1818145449b1SDimitry Andric     Opts.setInlining(CodeGenOptions::NormalInlining);
1819bab175ecSDimitry Andric   }
1820bab175ecSDimitry Andric 
1821b60736ecSDimitry Andric   // PIC defaults to -fno-direct-access-external-data while non-PIC defaults to
1822b60736ecSDimitry Andric   // -fdirect-access-external-data.
1823b60736ecSDimitry Andric   Opts.DirectAccessExternalData =
1824b60736ecSDimitry Andric       Args.hasArg(OPT_fdirect_access_external_data) ||
1825b60736ecSDimitry Andric       (!Args.hasArg(OPT_fno_direct_access_external_data) &&
1826344a3780SDimitry Andric        LangOpts->PICLevel == 0);
1827344a3780SDimitry Andric 
1828344a3780SDimitry Andric   if (Arg *A = Args.getLastArg(OPT_debug_info_kind_EQ)) {
1829344a3780SDimitry Andric     unsigned Val =
1830344a3780SDimitry Andric         llvm::StringSwitch<unsigned>(A->getValue())
18317fa27ce4SDimitry Andric             .Case("line-tables-only", llvm::codegenoptions::DebugLineTablesOnly)
18327fa27ce4SDimitry Andric             .Case("line-directives-only",
18337fa27ce4SDimitry Andric                   llvm::codegenoptions::DebugDirectivesOnly)
18347fa27ce4SDimitry Andric             .Case("constructor", llvm::codegenoptions::DebugInfoConstructor)
18357fa27ce4SDimitry Andric             .Case("limited", llvm::codegenoptions::LimitedDebugInfo)
18367fa27ce4SDimitry Andric             .Case("standalone", llvm::codegenoptions::FullDebugInfo)
18377fa27ce4SDimitry Andric             .Case("unused-types", llvm::codegenoptions::UnusedTypeInfo)
1838344a3780SDimitry Andric             .Default(~0U);
1839344a3780SDimitry Andric     if (Val == ~0U)
1840344a3780SDimitry Andric       Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
1841344a3780SDimitry Andric                                                 << A->getValue();
1842344a3780SDimitry Andric     else
18437fa27ce4SDimitry Andric       Opts.setDebugInfo(static_cast<llvm::codegenoptions::DebugInfoKind>(Val));
1844344a3780SDimitry Andric   }
18451569ce68SRoman Divacky 
1846b60736ecSDimitry Andric   // If -fuse-ctor-homing is set and limited debug info is already on, then use
1847344a3780SDimitry Andric   // constructor homing, and vice versa for -fno-use-ctor-homing.
1848344a3780SDimitry Andric   if (const Arg *A =
1849344a3780SDimitry Andric           Args.getLastArg(OPT_fuse_ctor_homing, OPT_fno_use_ctor_homing)) {
1850344a3780SDimitry Andric     if (A->getOption().matches(OPT_fuse_ctor_homing) &&
18517fa27ce4SDimitry Andric         Opts.getDebugInfo() == llvm::codegenoptions::LimitedDebugInfo)
18527fa27ce4SDimitry Andric       Opts.setDebugInfo(llvm::codegenoptions::DebugInfoConstructor);
1853344a3780SDimitry Andric     if (A->getOption().matches(OPT_fno_use_ctor_homing) &&
18547fa27ce4SDimitry Andric         Opts.getDebugInfo() == llvm::codegenoptions::DebugInfoConstructor)
18557fa27ce4SDimitry Andric       Opts.setDebugInfo(llvm::codegenoptions::LimitedDebugInfo);
1856344a3780SDimitry Andric   }
185745b53394SDimitry Andric 
1858cfca06d7SDimitry Andric   for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) {
1859cfca06d7SDimitry Andric     auto Split = StringRef(Arg).split('=');
18607fa27ce4SDimitry Andric     Opts.DebugPrefixMap.emplace_back(Split.first, Split.second);
1861cfca06d7SDimitry Andric   }
186256d91b49SDimitry Andric 
1863344a3780SDimitry Andric   for (const auto &Arg : Args.getAllArgValues(OPT_fcoverage_prefix_map_EQ)) {
1864b60736ecSDimitry Andric     auto Split = StringRef(Arg).split('=');
18657fa27ce4SDimitry Andric     Opts.CoveragePrefixMap.emplace_back(Split.first, Split.second);
1866b60736ecSDimitry Andric   }
186722989816SDimitry Andric 
1868519fc96cSDimitry Andric   const llvm::Triple::ArchType DebugEntryValueArchs[] = {
1869519fc96cSDimitry Andric       llvm::Triple::x86, llvm::Triple::x86_64, llvm::Triple::aarch64,
1870cfca06d7SDimitry Andric       llvm::Triple::arm, llvm::Triple::armeb, llvm::Triple::mips,
1871cfca06d7SDimitry Andric       llvm::Triple::mipsel, llvm::Triple::mips64, llvm::Triple::mips64el};
1872519fc96cSDimitry Andric 
1873706b4fc4SDimitry Andric   if (Opts.OptimizationLevel > 0 && Opts.hasReducedDebugInfo() &&
1874519fc96cSDimitry Andric       llvm::is_contained(DebugEntryValueArchs, T.getArch()))
1875cfca06d7SDimitry Andric     Opts.EmitCallSiteInfo = true;
187622989816SDimitry Andric 
1877344a3780SDimitry Andric   if (!Opts.EnableDIPreservationVerify && Opts.DIBugsReportFilePath.size()) {
1878344a3780SDimitry Andric     Diags.Report(diag::warn_ignoring_verify_debuginfo_preserve_export)
1879344a3780SDimitry Andric         << Opts.DIBugsReportFilePath;
1880344a3780SDimitry Andric     Opts.DIBugsReportFilePath = "";
1881344a3780SDimitry Andric   }
1882344a3780SDimitry Andric 
1883461a67faSDimitry Andric   Opts.NewStructPathTBAA = !Args.hasArg(OPT_no_struct_path_tbaa) &&
1884461a67faSDimitry Andric                            Args.hasArg(OPT_new_struct_path_tbaa);
18856a037251SDimitry Andric   Opts.OptimizeSize = getOptimizationLevelSize(Args);
1886344a3780SDimitry Andric   Opts.SimplifyLibCalls = !LangOpts->NoBuiltin;
188797b17066SDimitry Andric   if (Opts.SimplifyLibCalls)
1888344a3780SDimitry Andric     Opts.NoBuiltinFuncs = LangOpts->NoBuiltinFuncs;
1889bfef3995SDimitry Andric   Opts.UnrollLoops =
1890bfef3995SDimitry Andric       Args.hasFlag(OPT_funroll_loops, OPT_fno_unroll_loops,
18912b6b257fSDimitry Andric                    (Opts.OptimizationLevel > 1));
1892b60736ecSDimitry Andric   Opts.BinutilsVersion =
1893b60736ecSDimitry Andric       std::string(Args.getLastArgValue(OPT_fbinutils_version_EQ));
1894b60736ecSDimitry Andric 
1895ac9a064cSDimitry Andric   Opts.DebugTemplateAlias = Args.hasArg(OPT_gtemplate_alias);
1896ac9a064cSDimitry Andric 
1897676fbe81SDimitry Andric   Opts.DebugNameTable = static_cast<unsigned>(
1898676fbe81SDimitry Andric       Args.hasArg(OPT_ggnu_pubnames)
1899676fbe81SDimitry Andric           ? llvm::DICompileUnit::DebugNameTableKind::GNU
1900676fbe81SDimitry Andric           : Args.hasArg(OPT_gpubnames)
1901676fbe81SDimitry Andric                 ? llvm::DICompileUnit::DebugNameTableKind::Default
1902676fbe81SDimitry Andric                 : llvm::DICompileUnit::DebugNameTableKind::None);
1903c0981da4SDimitry Andric   if (const Arg *A = Args.getLastArg(OPT_gsimple_template_names_EQ)) {
1904c0981da4SDimitry Andric     StringRef Value = A->getValue();
1905c0981da4SDimitry Andric     if (Value != "simple" && Value != "mangled")
1906c0981da4SDimitry Andric       Diags.Report(diag::err_drv_unsupported_option_argument)
1907e3b55780SDimitry Andric           << A->getSpelling() << A->getValue();
1908c0981da4SDimitry Andric     Opts.setDebugSimpleTemplateNames(
1909c0981da4SDimitry Andric         StringRef(A->getValue()) == "simple"
19107fa27ce4SDimitry Andric             ? llvm::codegenoptions::DebugTemplateNamesKind::Simple
19117fa27ce4SDimitry Andric             : llvm::codegenoptions::DebugTemplateNamesKind::Mangled);
1912c0981da4SDimitry Andric   }
19132b6b257fSDimitry Andric 
1914b60736ecSDimitry Andric   if (const Arg *A = Args.getLastArg(OPT_ftime_report, OPT_ftime_report_EQ)) {
1915b60736ecSDimitry Andric     Opts.TimePasses = true;
1916b60736ecSDimitry Andric 
1917b60736ecSDimitry Andric     // -ftime-report= is only for new pass manager.
1918b60736ecSDimitry Andric     if (A->getOption().getID() == OPT_ftime_report_EQ) {
1919b60736ecSDimitry Andric       StringRef Val = A->getValue();
1920b60736ecSDimitry Andric       if (Val == "per-pass")
1921b60736ecSDimitry Andric         Opts.TimePassesPerRun = false;
1922b60736ecSDimitry Andric       else if (Val == "per-pass-run")
1923b60736ecSDimitry Andric         Opts.TimePassesPerRun = true;
1924b60736ecSDimitry Andric       else
192506d4ba38SDimitry Andric         Diags.Report(diag::err_drv_invalid_value)
1926b60736ecSDimitry Andric             << A->getAsString(Args) << A->getValue();
1927b60736ecSDimitry Andric     }
1928b60736ecSDimitry Andric   }
1929cfca06d7SDimitry Andric 
1930c0981da4SDimitry Andric   Opts.PrepareForLTO = false;
193148675466SDimitry Andric   Opts.PrepareForThinLTO = false;
1932325377b5SDimitry Andric   if (Arg *A = Args.getLastArg(OPT_flto_EQ)) {
1933c0981da4SDimitry Andric     Opts.PrepareForLTO = true;
1934325377b5SDimitry Andric     StringRef S = A->getValue();
1935325377b5SDimitry Andric     if (S == "thin")
193648675466SDimitry Andric       Opts.PrepareForThinLTO = true;
1937325377b5SDimitry Andric     else if (S != "full")
1938325377b5SDimitry Andric       Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << S;
19397fa27ce4SDimitry Andric     if (Args.hasArg(OPT_funified_lto))
19407fa27ce4SDimitry Andric       Opts.PrepareForThinLTO = true;
1941325377b5SDimitry Andric   }
194245b53394SDimitry Andric   if (Arg *A = Args.getLastArg(OPT_fthinlto_index_EQ)) {
1943519fc96cSDimitry Andric     if (IK.getLanguage() != Language::LLVM_IR)
194445b53394SDimitry Andric       Diags.Report(diag::err_drv_argument_only_allowed_with)
194545b53394SDimitry Andric           << A->getAsString(Args) << "-x ir";
1946cfca06d7SDimitry Andric     Opts.ThinLTOIndexFile =
1947cfca06d7SDimitry Andric         std::string(Args.getLastArgValue(OPT_fthinlto_index_EQ));
194845b53394SDimitry Andric   }
194948675466SDimitry Andric   if (Arg *A = Args.getLastArg(OPT_save_temps_EQ))
195048675466SDimitry Andric     Opts.SaveTempsFilePrefix =
195148675466SDimitry Andric         llvm::StringSwitch<std::string>(A->getValue())
1952b60736ecSDimitry Andric             .Case("obj", OutputFile)
1953b60736ecSDimitry Andric             .Default(llvm::sys::path::filename(OutputFile).str());
195448675466SDimitry Andric 
1955b60736ecSDimitry Andric   // The memory profile runtime appends the pid to make this name more unique.
1956b60736ecSDimitry Andric   const char *MemProfileBasename = "memprof.profraw";
1957b60736ecSDimitry Andric   if (Args.hasArg(OPT_fmemory_profile_EQ)) {
1958b60736ecSDimitry Andric     SmallString<128> Path(
1959b60736ecSDimitry Andric         std::string(Args.getLastArgValue(OPT_fmemory_profile_EQ)));
1960b60736ecSDimitry Andric     llvm::sys::path::append(Path, MemProfileBasename);
1961b60736ecSDimitry Andric     Opts.MemoryProfileOutput = std::string(Path);
1962b60736ecSDimitry Andric   } else if (Args.hasArg(OPT_fmemory_profile))
1963b60736ecSDimitry Andric     Opts.MemoryProfileOutput = MemProfileBasename;
196451ece4aaSDimitry Andric 
1965344a3780SDimitry Andric   memcpy(Opts.CoverageVersion, "408*", 4);
19667fa27ce4SDimitry Andric   if (Opts.CoverageNotesFile.size() || Opts.CoverageDataFile.size()) {
1967809500fcSDimitry Andric     if (Args.hasArg(OPT_coverage_version_EQ)) {
1968809500fcSDimitry Andric       StringRef CoverageVersion = Args.getLastArgValue(OPT_coverage_version_EQ);
1969809500fcSDimitry Andric       if (CoverageVersion.size() != 4) {
1970809500fcSDimitry Andric         Diags.Report(diag::err_drv_invalid_value)
1971809500fcSDimitry Andric             << Args.getLastArg(OPT_coverage_version_EQ)->getAsString(Args)
1972809500fcSDimitry Andric             << CoverageVersion;
1973809500fcSDimitry Andric       } else {
1974809500fcSDimitry Andric         memcpy(Opts.CoverageVersion, CoverageVersion.data(), 4);
1975809500fcSDimitry Andric       }
1976809500fcSDimitry Andric     }
1977809500fcSDimitry Andric   }
19782b6b257fSDimitry Andric   // FIXME: For backend options that are not yet recorded as function
19792b6b257fSDimitry Andric   // attributes in the IR, keep track of them so we can embed them in a
19802b6b257fSDimitry Andric   // separate data section and use them when building the bitcode.
19812b6b257fSDimitry Andric   for (const auto &A : Args) {
19822b6b257fSDimitry Andric     // Do not encode output and input.
19832b6b257fSDimitry Andric     if (A->getOption().getID() == options::OPT_o ||
19842b6b257fSDimitry Andric         A->getOption().getID() == options::OPT_INPUT ||
19852b6b257fSDimitry Andric         A->getOption().getID() == options::OPT_x ||
19862b6b257fSDimitry Andric         A->getOption().getID() == options::OPT_fembed_bitcode ||
1987cfca06d7SDimitry Andric         A->getOption().matches(options::OPT_W_Group))
19882b6b257fSDimitry Andric       continue;
19892b6b257fSDimitry Andric     ArgStringList ASL;
19902b6b257fSDimitry Andric     A->render(Args, ASL);
19912b6b257fSDimitry Andric     for (const auto &arg : ASL) {
19922b6b257fSDimitry Andric       StringRef ArgStr(arg);
19932b6b257fSDimitry Andric       Opts.CmdArgs.insert(Opts.CmdArgs.end(), ArgStr.begin(), ArgStr.end());
1994676fbe81SDimitry Andric       // using \00 to separate each commandline options.
19952b6b257fSDimitry Andric       Opts.CmdArgs.push_back('\0');
19962b6b257fSDimitry Andric     }
19972b6b257fSDimitry Andric   }
199848675466SDimitry Andric 
199948675466SDimitry Andric   auto XRayInstrBundles =
200048675466SDimitry Andric       Args.getAllArgValues(OPT_fxray_instrumentation_bundle);
200148675466SDimitry Andric   if (XRayInstrBundles.empty())
200248675466SDimitry Andric     Opts.XRayInstrumentationBundle.Mask = XRayInstrKind::All;
200348675466SDimitry Andric   else
200448675466SDimitry Andric     for (const auto &A : XRayInstrBundles)
200548675466SDimitry Andric       parseXRayInstrumentationBundle("-fxray-instrumentation-bundle=", A, Args,
200648675466SDimitry Andric                                      Diags, Opts.XRayInstrumentationBundle);
200748675466SDimitry Andric 
200848675466SDimitry Andric   if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) {
200948675466SDimitry Andric     StringRef Name = A->getValue();
201048675466SDimitry Andric     if (Name == "full") {
201148675466SDimitry Andric       Opts.CFProtectionReturn = 1;
201248675466SDimitry Andric       Opts.CFProtectionBranch = 1;
201348675466SDimitry Andric     } else if (Name == "return")
201448675466SDimitry Andric       Opts.CFProtectionReturn = 1;
201548675466SDimitry Andric     else if (Name == "branch")
201648675466SDimitry Andric       Opts.CFProtectionBranch = 1;
2017344a3780SDimitry Andric     else if (Name != "none")
201848675466SDimitry Andric       Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
201948675466SDimitry Andric   }
202048675466SDimitry Andric 
20211f917f69SDimitry Andric   if (const Arg *A = Args.getLastArg(OPT_mfunction_return_EQ)) {
20221f917f69SDimitry Andric     auto Val = llvm::StringSwitch<llvm::FunctionReturnThunksKind>(A->getValue())
20231f917f69SDimitry Andric                    .Case("keep", llvm::FunctionReturnThunksKind::Keep)
20241f917f69SDimitry Andric                    .Case("thunk-extern", llvm::FunctionReturnThunksKind::Extern)
20251f917f69SDimitry Andric                    .Default(llvm::FunctionReturnThunksKind::Invalid);
20261f917f69SDimitry Andric     // SystemZ might want to add support for "expolines."
20271f917f69SDimitry Andric     if (!T.isX86())
20281f917f69SDimitry Andric       Diags.Report(diag::err_drv_argument_not_allowed_with)
20291f917f69SDimitry Andric           << A->getSpelling() << T.getTriple();
20301f917f69SDimitry Andric     else if (Val == llvm::FunctionReturnThunksKind::Invalid)
20311f917f69SDimitry Andric       Diags.Report(diag::err_drv_invalid_value)
20321f917f69SDimitry Andric           << A->getAsString(Args) << A->getValue();
20331f917f69SDimitry Andric     else if (Val == llvm::FunctionReturnThunksKind::Extern &&
2034ac9a064cSDimitry Andric              Args.getLastArgValue(OPT_mcmodel_EQ) == "large")
20351f917f69SDimitry Andric       Diags.Report(diag::err_drv_argument_not_allowed_with)
20361f917f69SDimitry Andric           << A->getAsString(Args)
20371f917f69SDimitry Andric           << Args.getLastArg(OPT_mcmodel_EQ)->getAsString(Args);
20381f917f69SDimitry Andric     else
20391f917f69SDimitry Andric       Opts.FunctionReturnThunks = static_cast<unsigned>(Val);
20401f917f69SDimitry Andric   }
20411f917f69SDimitry Andric 
204248675466SDimitry Andric   for (auto *A :
2043676fbe81SDimitry Andric        Args.filtered(OPT_mlink_bitcode_file, OPT_mlink_builtin_bitcode)) {
20447442d6faSDimitry Andric     CodeGenOptions::BitcodeFileToLink F;
20457442d6faSDimitry Andric     F.Filename = A->getValue();
2046676fbe81SDimitry Andric     if (A->getOption().matches(OPT_mlink_builtin_bitcode)) {
20477442d6faSDimitry Andric       F.LinkFlags = llvm::Linker::Flags::LinkOnlyNeeded;
20487442d6faSDimitry Andric       // When linking CUDA bitcode, propagate function attributes so that
20497442d6faSDimitry Andric       // e.g. libdevice gets fast-math attrs if we're building with fast-math.
20507442d6faSDimitry Andric       F.PropagateAttrs = true;
20517442d6faSDimitry Andric       F.Internalize = true;
20527442d6faSDimitry Andric     }
20537442d6faSDimitry Andric     Opts.LinkBitcodeFiles.push_back(F);
205445b53394SDimitry Andric   }
2055676fbe81SDimitry Andric 
2056bab175ecSDimitry Andric   if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_EQ)) {
2057bab175ecSDimitry Andric     StringRef Val = A->getValue();
2058706b4fc4SDimitry Andric     Opts.FPDenormalMode = llvm::parseDenormalFPAttribute(Val);
2059145449b1SDimitry Andric     Opts.FP32DenormalMode = Opts.FPDenormalMode;
2060cfca06d7SDimitry Andric     if (!Opts.FPDenormalMode.isValid())
2061bab175ecSDimitry Andric       Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
2062bab175ecSDimitry Andric   }
2063bab175ecSDimitry Andric 
2064cfca06d7SDimitry Andric   if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_f32_EQ)) {
2065cfca06d7SDimitry Andric     StringRef Val = A->getValue();
2066cfca06d7SDimitry Andric     Opts.FP32DenormalMode = llvm::parseDenormalFPAttribute(Val);
2067cfca06d7SDimitry Andric     if (!Opts.FP32DenormalMode.isValid())
2068cfca06d7SDimitry Andric       Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
2069cfca06d7SDimitry Andric   }
2070cfca06d7SDimitry Andric 
2071cfca06d7SDimitry Andric   // X86_32 has -fppc-struct-return and -freg-struct-return.
2072cfca06d7SDimitry Andric   // PPC32 has -maix-struct-return and -msvr4-struct-return.
2073cfca06d7SDimitry Andric   if (Arg *A =
2074cfca06d7SDimitry Andric           Args.getLastArg(OPT_fpcc_struct_return, OPT_freg_struct_return,
2075cfca06d7SDimitry Andric                           OPT_maix_struct_return, OPT_msvr4_struct_return)) {
2076cfca06d7SDimitry Andric     // TODO: We might want to consider enabling these options on AIX in the
2077cfca06d7SDimitry Andric     // future.
2078cfca06d7SDimitry Andric     if (T.isOSAIX())
2079cfca06d7SDimitry Andric       Diags.Report(diag::err_drv_unsupported_opt_for_target)
2080cfca06d7SDimitry Andric           << A->getSpelling() << T.str();
2081cfca06d7SDimitry Andric 
2082cfca06d7SDimitry Andric     const Option &O = A->getOption();
2083cfca06d7SDimitry Andric     if (O.matches(OPT_fpcc_struct_return) ||
2084cfca06d7SDimitry Andric         O.matches(OPT_maix_struct_return)) {
2085bfef3995SDimitry Andric       Opts.setStructReturnConvention(CodeGenOptions::SRCK_OnStack);
2086bfef3995SDimitry Andric     } else {
2087cfca06d7SDimitry Andric       assert(O.matches(OPT_freg_struct_return) ||
2088cfca06d7SDimitry Andric              O.matches(OPT_msvr4_struct_return));
2089bfef3995SDimitry Andric       Opts.setStructReturnConvention(CodeGenOptions::SRCK_InRegs);
2090bfef3995SDimitry Andric     }
2091bfef3995SDimitry Andric   }
2092bfef3995SDimitry Andric 
20937fa27ce4SDimitry Andric   if (Arg *A = Args.getLastArg(OPT_mxcoff_roptr)) {
2094b60736ecSDimitry Andric     if (!T.isOSAIX())
2095b60736ecSDimitry Andric       Diags.Report(diag::err_drv_unsupported_opt_for_target)
2096b60736ecSDimitry Andric           << A->getSpelling() << T.str();
2097b60736ecSDimitry Andric 
20987fa27ce4SDimitry Andric     // Since the storage mapping class is specified per csect,
20997fa27ce4SDimitry Andric     // without using data sections, it is less effective to use read-only
21007fa27ce4SDimitry Andric     // pointers. Using read-only pointers may cause other RO variables in the
21017fa27ce4SDimitry Andric     // same csect to become RW when the linker acts upon `-bforceimprw`;
21027fa27ce4SDimitry Andric     // therefore, we require that separate data sections
21037fa27ce4SDimitry Andric     // are used when `-mxcoff-roptr` is in effect. We respect the setting of
21047fa27ce4SDimitry Andric     // data-sections since we have not found reasons to do otherwise that
21057fa27ce4SDimitry Andric     // overcome the user surprise of not respecting the setting.
21067fa27ce4SDimitry Andric     if (!Args.hasFlag(OPT_fdata_sections, OPT_fno_data_sections, false))
21077fa27ce4SDimitry Andric       Diags.Report(diag::err_roptr_requires_data_sections);
21087fa27ce4SDimitry Andric 
21097fa27ce4SDimitry Andric     Opts.XCOFFReadOnlyPointers = true;
2110b60736ecSDimitry Andric   }
2111b60736ecSDimitry Andric 
211208e8dd7bSDimitry Andric   if (Arg *A = Args.getLastArg(OPT_mabi_EQ_quadword_atomics)) {
211308e8dd7bSDimitry Andric     if (!T.isOSAIX() || T.isPPC32())
211408e8dd7bSDimitry Andric       Diags.Report(diag::err_drv_unsupported_opt_for_target)
211508e8dd7bSDimitry Andric         << A->getSpelling() << T.str();
211608e8dd7bSDimitry Andric   }
211708e8dd7bSDimitry Andric 
21189f4dbff6SDimitry Andric   bool NeedLocTracking = false;
21199f4dbff6SDimitry Andric 
2120bab175ecSDimitry Andric   if (!Opts.OptRecordFile.empty())
2121bab175ecSDimitry Andric     NeedLocTracking = true;
2122bab175ecSDimitry Andric 
212322989816SDimitry Andric   if (Arg *A = Args.getLastArg(OPT_opt_record_passes)) {
212422989816SDimitry Andric     Opts.OptRecordPasses = A->getValue();
212522989816SDimitry Andric     NeedLocTracking = true;
212622989816SDimitry Andric   }
212722989816SDimitry Andric 
212822989816SDimitry Andric   if (Arg *A = Args.getLastArg(OPT_opt_record_format)) {
212922989816SDimitry Andric     Opts.OptRecordFormat = A->getValue();
213022989816SDimitry Andric     NeedLocTracking = true;
213122989816SDimitry Andric   }
213222989816SDimitry Andric 
2133344a3780SDimitry Andric   Opts.OptimizationRemark =
2134344a3780SDimitry Andric       ParseOptimizationRemark(Diags, Args, OPT_Rpass_EQ, "pass");
21359f4dbff6SDimitry Andric 
2136344a3780SDimitry Andric   Opts.OptimizationRemarkMissed =
2137344a3780SDimitry Andric       ParseOptimizationRemark(Diags, Args, OPT_Rpass_missed_EQ, "pass-missed");
21389f4dbff6SDimitry Andric 
2139344a3780SDimitry Andric   Opts.OptimizationRemarkAnalysis = ParseOptimizationRemark(
2140344a3780SDimitry Andric       Diags, Args, OPT_Rpass_analysis_EQ, "pass-analysis");
2141344a3780SDimitry Andric 
2142344a3780SDimitry Andric   NeedLocTracking |= Opts.OptimizationRemark.hasValidPattern() ||
2143344a3780SDimitry Andric                      Opts.OptimizationRemarkMissed.hasValidPattern() ||
2144344a3780SDimitry Andric                      Opts.OptimizationRemarkAnalysis.hasValidPattern();
21459f4dbff6SDimitry Andric 
2146ef915aabSDimitry Andric   bool UsingSampleProfile = !Opts.SampleProfileFile.empty();
21477fa27ce4SDimitry Andric   bool UsingProfile =
21487fa27ce4SDimitry Andric       UsingSampleProfile || !Opts.ProfileInstrumentUsePath.empty();
2149ef915aabSDimitry Andric 
215048675466SDimitry Andric   if (Opts.DiagnosticsWithHotness && !UsingProfile &&
215148675466SDimitry Andric       // An IR file will contain PGO as metadata
2152519fc96cSDimitry Andric       IK.getLanguage() != Language::LLVM_IR)
2153cf1b4019SDimitry Andric     Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo)
2154cf1b4019SDimitry Andric         << "-fdiagnostics-show-hotness";
2155cf1b4019SDimitry Andric 
2156b60736ecSDimitry Andric   // Parse remarks hotness threshold. Valid value is either integer or 'auto'.
2157b60736ecSDimitry Andric   if (auto *arg =
2158b60736ecSDimitry Andric           Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) {
2159b60736ecSDimitry Andric     auto ResultOrErr =
2160b60736ecSDimitry Andric         llvm::remarks::parseHotnessThresholdOption(arg->getValue());
2161b60736ecSDimitry Andric 
2162b60736ecSDimitry Andric     if (!ResultOrErr) {
2163b60736ecSDimitry Andric       Diags.Report(diag::err_drv_invalid_diagnotics_hotness_threshold)
2164b60736ecSDimitry Andric           << "-fdiagnostics-hotness-threshold=";
2165b60736ecSDimitry Andric     } else {
2166b60736ecSDimitry Andric       Opts.DiagnosticsHotnessThreshold = *ResultOrErr;
2167145449b1SDimitry Andric       if ((!Opts.DiagnosticsHotnessThreshold ||
2168e3b55780SDimitry Andric            *Opts.DiagnosticsHotnessThreshold > 0) &&
2169b60736ecSDimitry Andric           !UsingProfile)
2170cf1b4019SDimitry Andric         Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo)
2171cf1b4019SDimitry Andric             << "-fdiagnostics-hotness-threshold=";
2172b60736ecSDimitry Andric     }
2173b60736ecSDimitry Andric   }
2174bab175ecSDimitry Andric 
2175145449b1SDimitry Andric   if (auto *arg =
2176145449b1SDimitry Andric           Args.getLastArg(options::OPT_fdiagnostics_misexpect_tolerance_EQ)) {
2177145449b1SDimitry Andric     auto ResultOrErr = parseToleranceOption(arg->getValue());
2178145449b1SDimitry Andric 
2179145449b1SDimitry Andric     if (!ResultOrErr) {
2180145449b1SDimitry Andric       Diags.Report(diag::err_drv_invalid_diagnotics_misexpect_tolerance)
2181145449b1SDimitry Andric           << "-fdiagnostics-misexpect-tolerance=";
2182145449b1SDimitry Andric     } else {
2183145449b1SDimitry Andric       Opts.DiagnosticsMisExpectTolerance = *ResultOrErr;
2184145449b1SDimitry Andric       if ((!Opts.DiagnosticsMisExpectTolerance ||
2185e3b55780SDimitry Andric            *Opts.DiagnosticsMisExpectTolerance > 0) &&
2186145449b1SDimitry Andric           !UsingProfile)
2187145449b1SDimitry Andric         Diags.Report(diag::warn_drv_diagnostics_misexpect_requires_pgo)
2188145449b1SDimitry Andric             << "-fdiagnostics-misexpect-tolerance=";
2189145449b1SDimitry Andric     }
2190145449b1SDimitry Andric   }
2191145449b1SDimitry Andric 
219206d4ba38SDimitry Andric   // If the user requested to use a sample profile for PGO, then the
219306d4ba38SDimitry Andric   // backend will need to track source location information so the profile
219406d4ba38SDimitry Andric   // can be incorporated into the IR.
2195ef915aabSDimitry Andric   if (UsingSampleProfile)
219606d4ba38SDimitry Andric     NeedLocTracking = true;
219706d4ba38SDimitry Andric 
2198344a3780SDimitry Andric   if (!Opts.StackUsageOutput.empty())
2199344a3780SDimitry Andric     NeedLocTracking = true;
2200344a3780SDimitry Andric 
220106d4ba38SDimitry Andric   // If the user requested a flag that requires source locations available in
220206d4ba38SDimitry Andric   // the backend, make sure that the backend tracks source location information.
22037fa27ce4SDimitry Andric   if (NeedLocTracking &&
22047fa27ce4SDimitry Andric       Opts.getDebugInfo() == llvm::codegenoptions::NoDebugInfo)
22057fa27ce4SDimitry Andric     Opts.setDebugInfo(llvm::codegenoptions::LocTrackingOnly);
2206bfef3995SDimitry Andric 
220706d4ba38SDimitry Andric   // Parse -fsanitize-recover= arguments.
220806d4ba38SDimitry Andric   // FIXME: Report unrecoverable sanitizers incorrectly specified here.
220906d4ba38SDimitry Andric   parseSanitizerKinds("-fsanitize-recover=",
221006d4ba38SDimitry Andric                       Args.getAllArgValues(OPT_fsanitize_recover_EQ), Diags,
221106d4ba38SDimitry Andric                       Opts.SanitizeRecover);
22122e645aa5SDimitry Andric   parseSanitizerKinds("-fsanitize-trap=",
22132e645aa5SDimitry Andric                       Args.getAllArgValues(OPT_fsanitize_trap_EQ), Diags,
22142e645aa5SDimitry Andric                       Opts.SanitizeTrap);
221506d4ba38SDimitry Andric 
221648675466SDimitry Andric   Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true);
221748675466SDimitry Andric 
2218ac9a064cSDimitry Andric   if (!LangOpts->CUDAIsDevice)
2219ac9a064cSDimitry Andric     parsePointerAuthOptions(Opts.PointerAuth, *LangOpts, T, Diags);
2220ac9a064cSDimitry Andric 
2221344a3780SDimitry Andric   if (Args.hasArg(options::OPT_ffinite_loops))
2222344a3780SDimitry Andric     Opts.FiniteLoops = CodeGenOptions::FiniteLoopsKind::Always;
2223344a3780SDimitry Andric   else if (Args.hasArg(options::OPT_fno_finite_loops))
2224344a3780SDimitry Andric     Opts.FiniteLoops = CodeGenOptions::FiniteLoopsKind::Never;
2225344a3780SDimitry Andric 
2226145449b1SDimitry Andric   Opts.EmitIEEENaNCompliantInsts = Args.hasFlag(
2227145449b1SDimitry Andric       options::OPT_mamdgpu_ieee, options::OPT_mno_amdgpu_ieee, true);
2228344a3780SDimitry Andric   if (!Opts.EmitIEEENaNCompliantInsts && !LangOptsRef.NoHonorNaNs)
2229344a3780SDimitry Andric     Diags.Report(diag::err_drv_amdgpu_ieee_without_no_honor_nans);
2230344a3780SDimitry Andric 
2231344a3780SDimitry Andric   return Diags.getNumErrors() == NumErrorsBefore;
2232dbe13110SDimitry Andric }
2233dbe13110SDimitry Andric 
GenerateDependencyOutputArgs(const DependencyOutputOptions & Opts,ArgumentConsumer Consumer)2234b1c73532SDimitry Andric static void GenerateDependencyOutputArgs(const DependencyOutputOptions &Opts,
2235b1c73532SDimitry Andric                                          ArgumentConsumer Consumer) {
2236344a3780SDimitry Andric   const DependencyOutputOptions &DependencyOutputOpts = Opts;
22377fa27ce4SDimitry Andric #define DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING(...)                         \
2238b1c73532SDimitry Andric   GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
2239344a3780SDimitry Andric #include "clang/Driver/Options.inc"
2240344a3780SDimitry Andric #undef DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING
2241344a3780SDimitry Andric 
2242344a3780SDimitry Andric   if (Opts.ShowIncludesDest != ShowIncludesDestination::None)
2243b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_show_includes);
2244344a3780SDimitry Andric 
2245344a3780SDimitry Andric   for (const auto &Dep : Opts.ExtraDeps) {
2246344a3780SDimitry Andric     switch (Dep.second) {
2247344a3780SDimitry Andric     case EDK_SanitizeIgnorelist:
2248344a3780SDimitry Andric       // Sanitizer ignorelist arguments are generated from LanguageOptions.
2249344a3780SDimitry Andric       continue;
2250344a3780SDimitry Andric     case EDK_ModuleFile:
2251344a3780SDimitry Andric       // Module file arguments are generated from FrontendOptions and
2252344a3780SDimitry Andric       // HeaderSearchOptions.
2253344a3780SDimitry Andric       continue;
2254344a3780SDimitry Andric     case EDK_ProfileList:
2255344a3780SDimitry Andric       // Profile list arguments are generated from LanguageOptions via the
2256344a3780SDimitry Andric       // marshalling infrastructure.
2257344a3780SDimitry Andric       continue;
2258344a3780SDimitry Andric     case EDK_DepFileEntry:
2259b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_fdepfile_entry, Dep.first);
2260344a3780SDimitry Andric       break;
2261344a3780SDimitry Andric     }
2262344a3780SDimitry Andric   }
2263344a3780SDimitry Andric }
2264344a3780SDimitry Andric 
ParseDependencyOutputArgs(DependencyOutputOptions & Opts,ArgList & Args,DiagnosticsEngine & Diags,frontend::ActionKind Action,bool ShowLineMarkers)2265344a3780SDimitry Andric static bool ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
2266344a3780SDimitry Andric                                       ArgList &Args, DiagnosticsEngine &Diags,
2267344a3780SDimitry Andric                                       frontend::ActionKind Action,
2268344a3780SDimitry Andric                                       bool ShowLineMarkers) {
2269344a3780SDimitry Andric   unsigned NumErrorsBefore = Diags.getNumErrors();
2270344a3780SDimitry Andric 
2271344a3780SDimitry Andric   DependencyOutputOptions &DependencyOutputOpts = Opts;
22727fa27ce4SDimitry Andric #define DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING(...)                         \
22737fa27ce4SDimitry Andric   PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
2274344a3780SDimitry Andric #include "clang/Driver/Options.inc"
2275344a3780SDimitry Andric #undef DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING
2276344a3780SDimitry Andric 
227748675466SDimitry Andric   if (Args.hasArg(OPT_show_includes)) {
227848675466SDimitry Andric     // Writing both /showIncludes and preprocessor output to stdout
227948675466SDimitry Andric     // would produce interleaved output, so use stderr for /showIncludes.
228048675466SDimitry Andric     // This behaves the same as cl.exe, when /E, /EP or /P are passed.
2281344a3780SDimitry Andric     if (Action == frontend::PrintPreprocessedInput || !ShowLineMarkers)
228248675466SDimitry Andric       Opts.ShowIncludesDest = ShowIncludesDestination::Stderr;
228348675466SDimitry Andric     else
228448675466SDimitry Andric       Opts.ShowIncludesDest = ShowIncludesDestination::Stdout;
228548675466SDimitry Andric   } else {
228648675466SDimitry Andric     Opts.ShowIncludesDest = ShowIncludesDestination::None;
228748675466SDimitry Andric   }
2288344a3780SDimitry Andric 
2289344a3780SDimitry Andric   // Add sanitizer ignorelists as extra dependencies.
229045b53394SDimitry Andric   // They won't be discovered by the regular preprocessor, so
229145b53394SDimitry Andric   // we let make / ninja to know about this implicit dependency.
2292344a3780SDimitry Andric   if (!Args.hasArg(OPT_fno_sanitize_ignorelist)) {
2293344a3780SDimitry Andric     for (const auto *A : Args.filtered(OPT_fsanitize_ignorelist_EQ)) {
2294706b4fc4SDimitry Andric       StringRef Val = A->getValue();
2295c0981da4SDimitry Andric       if (!Val.contains('='))
2296344a3780SDimitry Andric         Opts.ExtraDeps.emplace_back(std::string(Val), EDK_SanitizeIgnorelist);
2297706b4fc4SDimitry Andric     }
2298706b4fc4SDimitry Andric     if (Opts.IncludeSystemHeaders) {
2299344a3780SDimitry Andric       for (const auto *A : Args.filtered(OPT_fsanitize_system_ignorelist_EQ)) {
2300706b4fc4SDimitry Andric         StringRef Val = A->getValue();
2301c0981da4SDimitry Andric         if (!Val.contains('='))
2302344a3780SDimitry Andric           Opts.ExtraDeps.emplace_back(std::string(Val), EDK_SanitizeIgnorelist);
2303706b4fc4SDimitry Andric       }
2304706b4fc4SDimitry Andric     }
2305706b4fc4SDimitry Andric   }
2306706b4fc4SDimitry Andric 
2307b60736ecSDimitry Andric   // -fprofile-list= dependencies.
2308b60736ecSDimitry Andric   for (const auto &Filename : Args.getAllArgValues(OPT_fprofile_list_EQ))
2309344a3780SDimitry Andric     Opts.ExtraDeps.emplace_back(Filename, EDK_ProfileList);
2310b60736ecSDimitry Andric 
2311706b4fc4SDimitry Andric   // Propagate the extra dependencies.
2312344a3780SDimitry Andric   for (const auto *A : Args.filtered(OPT_fdepfile_entry))
2313344a3780SDimitry Andric     Opts.ExtraDeps.emplace_back(A->getValue(), EDK_DepFileEntry);
2314706b4fc4SDimitry Andric 
2315461a67faSDimitry Andric   // Only the -fmodule-file=<file> form.
231648675466SDimitry Andric   for (const auto *A : Args.filtered(OPT_fmodule_file)) {
2317461a67faSDimitry Andric     StringRef Val = A->getValue();
2318c0981da4SDimitry Andric     if (!Val.contains('='))
2319344a3780SDimitry Andric       Opts.ExtraDeps.emplace_back(std::string(Val), EDK_ModuleFile);
2320461a67faSDimitry Andric   }
2321344a3780SDimitry Andric 
2322e3b55780SDimitry Andric   // Check for invalid combinations of header-include-format
2323e3b55780SDimitry Andric   // and header-include-filtering.
2324e3b55780SDimitry Andric   if ((Opts.HeaderIncludeFormat == HIFMT_Textual &&
2325e3b55780SDimitry Andric        Opts.HeaderIncludeFiltering != HIFIL_None) ||
2326e3b55780SDimitry Andric       (Opts.HeaderIncludeFormat == HIFMT_JSON &&
2327e3b55780SDimitry Andric        Opts.HeaderIncludeFiltering != HIFIL_Only_Direct_System))
2328e3b55780SDimitry Andric     Diags.Report(diag::err_drv_print_header_env_var_combination_cc1)
2329e3b55780SDimitry Andric         << Args.getLastArg(OPT_header_include_format_EQ)->getValue()
2330e3b55780SDimitry Andric         << Args.getLastArg(OPT_header_include_filtering_EQ)->getValue();
2331e3b55780SDimitry Andric 
2332344a3780SDimitry Andric   return Diags.getNumErrors() == NumErrorsBefore;
23331569ce68SRoman Divacky }
23341569ce68SRoman Divacky 
parseShowColorsArgs(const ArgList & Args,bool DefaultColor)23352b6b257fSDimitry Andric static bool parseShowColorsArgs(const ArgList &Args, bool DefaultColor) {
23362b6b257fSDimitry Andric   // Color diagnostics default to auto ("on" if terminal supports) in the driver
23372b6b257fSDimitry Andric   // but default to off in cc1, needing an explicit OPT_fdiagnostics_color.
23382b6b257fSDimitry Andric   // Support both clang's -f[no-]color-diagnostics and gcc's
23392b6b257fSDimitry Andric   // -f[no-]diagnostics-colors[=never|always|auto].
23402b6b257fSDimitry Andric   enum {
23412b6b257fSDimitry Andric     Colors_On,
23422b6b257fSDimitry Andric     Colors_Off,
23432b6b257fSDimitry Andric     Colors_Auto
23442b6b257fSDimitry Andric   } ShowColors = DefaultColor ? Colors_Auto : Colors_Off;
234548675466SDimitry Andric   for (auto *A : Args) {
23462b6b257fSDimitry Andric     const Option &O = A->getOption();
2347145449b1SDimitry Andric     if (O.matches(options::OPT_fcolor_diagnostics)) {
23482b6b257fSDimitry Andric       ShowColors = Colors_On;
2349145449b1SDimitry Andric     } else if (O.matches(options::OPT_fno_color_diagnostics)) {
23502b6b257fSDimitry Andric       ShowColors = Colors_Off;
2351bab175ecSDimitry Andric     } else if (O.matches(options::OPT_fdiagnostics_color_EQ)) {
23522b6b257fSDimitry Andric       StringRef Value(A->getValue());
23532b6b257fSDimitry Andric       if (Value == "always")
23542b6b257fSDimitry Andric         ShowColors = Colors_On;
23552b6b257fSDimitry Andric       else if (Value == "never")
23562b6b257fSDimitry Andric         ShowColors = Colors_Off;
23572b6b257fSDimitry Andric       else if (Value == "auto")
23582b6b257fSDimitry Andric         ShowColors = Colors_Auto;
23592b6b257fSDimitry Andric     }
23602b6b257fSDimitry Andric   }
2361bab175ecSDimitry Andric   return ShowColors == Colors_On ||
2362bab175ecSDimitry Andric          (ShowColors == Colors_Auto &&
2363bab175ecSDimitry Andric           llvm::sys::Process::StandardErrHasColors());
23642b6b257fSDimitry Andric }
23652b6b257fSDimitry Andric 
checkVerifyPrefixes(const std::vector<std::string> & VerifyPrefixes,DiagnosticsEngine & Diags)2366461a67faSDimitry Andric static bool checkVerifyPrefixes(const std::vector<std::string> &VerifyPrefixes,
2367b60736ecSDimitry Andric                                 DiagnosticsEngine &Diags) {
2368461a67faSDimitry Andric   bool Success = true;
2369461a67faSDimitry Andric   for (const auto &Prefix : VerifyPrefixes) {
2370461a67faSDimitry Andric     // Every prefix must start with a letter and contain only alphanumeric
2371461a67faSDimitry Andric     // characters, hyphens, and underscores.
237222989816SDimitry Andric     auto BadChar = llvm::find_if(Prefix, [](char C) {
237322989816SDimitry Andric       return !isAlphanumeric(C) && C != '-' && C != '_';
237422989816SDimitry Andric     });
2375461a67faSDimitry Andric     if (BadChar != Prefix.end() || !isLetter(Prefix[0])) {
2376461a67faSDimitry Andric       Success = false;
2377b60736ecSDimitry Andric       Diags.Report(diag::err_drv_invalid_value) << "-verify=" << Prefix;
2378b60736ecSDimitry Andric       Diags.Report(diag::note_drv_verify_prefix_spelling);
2379461a67faSDimitry Andric     }
2380461a67faSDimitry Andric   }
2381b60736ecSDimitry Andric   return Success;
2382461a67faSDimitry Andric }
2383b60736ecSDimitry Andric 
GenerateFileSystemArgs(const FileSystemOptions & Opts,ArgumentConsumer Consumer)2384344a3780SDimitry Andric static void GenerateFileSystemArgs(const FileSystemOptions &Opts,
2385b1c73532SDimitry Andric                                    ArgumentConsumer Consumer) {
2386344a3780SDimitry Andric   const FileSystemOptions &FileSystemOpts = Opts;
2387b60736ecSDimitry Andric 
23887fa27ce4SDimitry Andric #define FILE_SYSTEM_OPTION_WITH_MARSHALLING(...)                               \
2389b1c73532SDimitry Andric   GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
2390b60736ecSDimitry Andric #include "clang/Driver/Options.inc"
2391344a3780SDimitry Andric #undef FILE_SYSTEM_OPTION_WITH_MARSHALLING
2392344a3780SDimitry Andric }
2393b60736ecSDimitry Andric 
ParseFileSystemArgs(FileSystemOptions & Opts,const ArgList & Args,DiagnosticsEngine & Diags)2394344a3780SDimitry Andric static bool ParseFileSystemArgs(FileSystemOptions &Opts, const ArgList &Args,
2395344a3780SDimitry Andric                                 DiagnosticsEngine &Diags) {
2396344a3780SDimitry Andric   unsigned NumErrorsBefore = Diags.getNumErrors();
2397344a3780SDimitry Andric 
2398344a3780SDimitry Andric   FileSystemOptions &FileSystemOpts = Opts;
2399344a3780SDimitry Andric 
24007fa27ce4SDimitry Andric #define FILE_SYSTEM_OPTION_WITH_MARSHALLING(...)                               \
24017fa27ce4SDimitry Andric   PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
2402344a3780SDimitry Andric #include "clang/Driver/Options.inc"
2403344a3780SDimitry Andric #undef FILE_SYSTEM_OPTION_WITH_MARSHALLING
2404344a3780SDimitry Andric 
2405344a3780SDimitry Andric   return Diags.getNumErrors() == NumErrorsBefore;
2406344a3780SDimitry Andric }
2407344a3780SDimitry Andric 
GenerateMigratorArgs(const MigratorOptions & Opts,ArgumentConsumer Consumer)2408344a3780SDimitry Andric static void GenerateMigratorArgs(const MigratorOptions &Opts,
2409b1c73532SDimitry Andric                                  ArgumentConsumer Consumer) {
2410344a3780SDimitry Andric   const MigratorOptions &MigratorOpts = Opts;
24117fa27ce4SDimitry Andric #define MIGRATOR_OPTION_WITH_MARSHALLING(...)                                  \
2412b1c73532SDimitry Andric   GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
2413344a3780SDimitry Andric #include "clang/Driver/Options.inc"
2414344a3780SDimitry Andric #undef MIGRATOR_OPTION_WITH_MARSHALLING
2415344a3780SDimitry Andric }
2416344a3780SDimitry Andric 
ParseMigratorArgs(MigratorOptions & Opts,const ArgList & Args,DiagnosticsEngine & Diags)2417344a3780SDimitry Andric static bool ParseMigratorArgs(MigratorOptions &Opts, const ArgList &Args,
2418344a3780SDimitry Andric                               DiagnosticsEngine &Diags) {
2419344a3780SDimitry Andric   unsigned NumErrorsBefore = Diags.getNumErrors();
2420344a3780SDimitry Andric 
2421344a3780SDimitry Andric   MigratorOptions &MigratorOpts = Opts;
2422344a3780SDimitry Andric 
24237fa27ce4SDimitry Andric #define MIGRATOR_OPTION_WITH_MARSHALLING(...)                                  \
24247fa27ce4SDimitry Andric   PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
2425344a3780SDimitry Andric #include "clang/Driver/Options.inc"
2426344a3780SDimitry Andric #undef MIGRATOR_OPTION_WITH_MARSHALLING
2427344a3780SDimitry Andric 
2428344a3780SDimitry Andric   return Diags.getNumErrors() == NumErrorsBefore;
2429344a3780SDimitry Andric }
2430344a3780SDimitry Andric 
GenerateDiagnosticArgs(const DiagnosticOptions & Opts,ArgumentConsumer Consumer,bool DefaultDiagColor)2431b1c73532SDimitry Andric void CompilerInvocationBase::GenerateDiagnosticArgs(
2432b1c73532SDimitry Andric     const DiagnosticOptions &Opts, ArgumentConsumer Consumer,
2433b1c73532SDimitry Andric     bool DefaultDiagColor) {
2434344a3780SDimitry Andric   const DiagnosticOptions *DiagnosticOpts = &Opts;
24357fa27ce4SDimitry Andric #define DIAG_OPTION_WITH_MARSHALLING(...)                                      \
2436b1c73532SDimitry Andric   GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
2437344a3780SDimitry Andric #include "clang/Driver/Options.inc"
2438344a3780SDimitry Andric #undef DIAG_OPTION_WITH_MARSHALLING
2439344a3780SDimitry Andric 
2440344a3780SDimitry Andric   if (!Opts.DiagnosticSerializationFile.empty())
2441b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_diagnostic_serialized_file,
2442b1c73532SDimitry Andric                 Opts.DiagnosticSerializationFile);
2443344a3780SDimitry Andric 
2444344a3780SDimitry Andric   if (Opts.ShowColors)
2445b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fcolor_diagnostics);
2446344a3780SDimitry Andric 
2447344a3780SDimitry Andric   if (Opts.VerifyDiagnostics &&
2448344a3780SDimitry Andric       llvm::is_contained(Opts.VerifyPrefixes, "expected"))
2449b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_verify);
2450344a3780SDimitry Andric 
2451344a3780SDimitry Andric   for (const auto &Prefix : Opts.VerifyPrefixes)
2452344a3780SDimitry Andric     if (Prefix != "expected")
2453b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_verify_EQ, Prefix);
2454344a3780SDimitry Andric 
2455344a3780SDimitry Andric   DiagnosticLevelMask VIU = Opts.getVerifyIgnoreUnexpected();
2456344a3780SDimitry Andric   if (VIU == DiagnosticLevelMask::None) {
2457344a3780SDimitry Andric     // This is the default, don't generate anything.
2458344a3780SDimitry Andric   } else if (VIU == DiagnosticLevelMask::All) {
2459b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_verify_ignore_unexpected);
2460344a3780SDimitry Andric   } else {
2461344a3780SDimitry Andric     if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Note) != 0)
2462b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "note");
2463344a3780SDimitry Andric     if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Remark) != 0)
2464b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "remark");
2465344a3780SDimitry Andric     if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Warning) != 0)
2466b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "warning");
2467344a3780SDimitry Andric     if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Error) != 0)
2468b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "error");
2469344a3780SDimitry Andric   }
2470344a3780SDimitry Andric 
2471344a3780SDimitry Andric   for (const auto &Warning : Opts.Warnings) {
2472344a3780SDimitry Andric     // This option is automatically generated from UndefPrefixes.
2473344a3780SDimitry Andric     if (Warning == "undef-prefix")
2474344a3780SDimitry Andric       continue;
2475ac9a064cSDimitry Andric     // This option is automatically generated from CheckConstexprFunctionBodies.
2476ac9a064cSDimitry Andric     if (Warning == "invalid-constexpr" || Warning == "no-invalid-constexpr")
2477ac9a064cSDimitry Andric       continue;
2478b1c73532SDimitry Andric     Consumer(StringRef("-W") + Warning);
2479344a3780SDimitry Andric   }
2480344a3780SDimitry Andric 
2481344a3780SDimitry Andric   for (const auto &Remark : Opts.Remarks) {
2482344a3780SDimitry Andric     // These arguments are generated from OptimizationRemark fields of
2483344a3780SDimitry Andric     // CodeGenOptions.
2484344a3780SDimitry Andric     StringRef IgnoredRemarks[] = {"pass",          "no-pass",
2485344a3780SDimitry Andric                                   "pass-analysis", "no-pass-analysis",
2486344a3780SDimitry Andric                                   "pass-missed",   "no-pass-missed"};
2487344a3780SDimitry Andric     if (llvm::is_contained(IgnoredRemarks, Remark))
2488344a3780SDimitry Andric       continue;
2489344a3780SDimitry Andric 
2490b1c73532SDimitry Andric     Consumer(StringRef("-R") + Remark);
2491344a3780SDimitry Andric   }
2492461a67faSDimitry Andric }
2493461a67faSDimitry Andric 
2494c0981da4SDimitry Andric std::unique_ptr<DiagnosticOptions>
CreateAndPopulateDiagOpts(ArrayRef<const char * > Argv)2495c0981da4SDimitry Andric clang::CreateAndPopulateDiagOpts(ArrayRef<const char *> Argv) {
2496c0981da4SDimitry Andric   auto DiagOpts = std::make_unique<DiagnosticOptions>();
2497c0981da4SDimitry Andric   unsigned MissingArgIndex, MissingArgCount;
2498c0981da4SDimitry Andric   InputArgList Args = getDriverOptTable().ParseArgs(
2499c0981da4SDimitry Andric       Argv.slice(1), MissingArgIndex, MissingArgCount);
25007fa27ce4SDimitry Andric 
25017fa27ce4SDimitry Andric   bool ShowColors = true;
25027fa27ce4SDimitry Andric   if (std::optional<std::string> NoColor =
25037fa27ce4SDimitry Andric           llvm::sys::Process::GetEnv("NO_COLOR");
25047fa27ce4SDimitry Andric       NoColor && !NoColor->empty()) {
25057fa27ce4SDimitry Andric     // If the user set the NO_COLOR environment variable, we'll honor that
25067fa27ce4SDimitry Andric     // unless the command line overrides it.
25077fa27ce4SDimitry Andric     ShowColors = false;
25087fa27ce4SDimitry Andric   }
25097fa27ce4SDimitry Andric 
2510c0981da4SDimitry Andric   // We ignore MissingArgCount and the return value of ParseDiagnosticArgs.
2511c0981da4SDimitry Andric   // Any errors that would be diagnosed here will also be diagnosed later,
2512c0981da4SDimitry Andric   // when the DiagnosticsEngine actually exists.
25137fa27ce4SDimitry Andric   (void)ParseDiagnosticArgs(*DiagOpts, Args, /*Diags=*/nullptr, ShowColors);
2514c0981da4SDimitry Andric   return DiagOpts;
2515c0981da4SDimitry Andric }
2516c0981da4SDimitry Andric 
ParseDiagnosticArgs(DiagnosticOptions & Opts,ArgList & Args,DiagnosticsEngine * Diags,bool DefaultDiagColor)2517dbe13110SDimitry Andric bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
25182b6b257fSDimitry Andric                                 DiagnosticsEngine *Diags,
2519cfca06d7SDimitry Andric                                 bool DefaultDiagColor) {
2520e3b55780SDimitry Andric   std::optional<DiagnosticsEngine> IgnoringDiags;
2521b60736ecSDimitry Andric   if (!Diags) {
2522b60736ecSDimitry Andric     IgnoringDiags.emplace(new DiagnosticIDs(), new DiagnosticOptions(),
2523b60736ecSDimitry Andric                           new IgnoringDiagConsumer());
2524b60736ecSDimitry Andric     Diags = &*IgnoringDiags;
2525b60736ecSDimitry Andric   }
2526b60736ecSDimitry Andric 
2527344a3780SDimitry Andric   unsigned NumErrorsBefore = Diags->getNumErrors();
2528344a3780SDimitry Andric 
2529b60736ecSDimitry Andric   // The key paths of diagnostic options defined in Options.td start with
2530b60736ecSDimitry Andric   // "DiagnosticOpts->". Let's provide the expected variable name and type.
2531b60736ecSDimitry Andric   DiagnosticOptions *DiagnosticOpts = &Opts;
2532dbe13110SDimitry Andric 
25337fa27ce4SDimitry Andric #define DIAG_OPTION_WITH_MARSHALLING(...)                                      \
25347fa27ce4SDimitry Andric   PARSE_OPTION_WITH_MARSHALLING(Args, *Diags, __VA_ARGS__)
2535b60736ecSDimitry Andric #include "clang/Driver/Options.inc"
2536b60736ecSDimitry Andric #undef DIAG_OPTION_WITH_MARSHALLING
2537b60736ecSDimitry Andric 
2538b60736ecSDimitry Andric   llvm::sys::Process::UseANSIEscapeCodes(Opts.UseANSIEscapeCodes);
2539b60736ecSDimitry Andric 
254006d4ba38SDimitry Andric   if (Arg *A =
254106d4ba38SDimitry Andric           Args.getLastArg(OPT_diagnostic_serialized_file, OPT__serialize_diags))
254206d4ba38SDimitry Andric     Opts.DiagnosticSerializationFile = A->getValue();
25432b6b257fSDimitry Andric   Opts.ShowColors = parseShowColorsArgs(Args, DefaultDiagColor);
2544bfef3995SDimitry Andric 
2545461a67faSDimitry Andric   Opts.VerifyDiagnostics = Args.hasArg(OPT_verify) || Args.hasArg(OPT_verify_EQ);
2546344a3780SDimitry Andric   Opts.VerifyPrefixes = Args.getAllArgValues(OPT_verify_EQ);
2547461a67faSDimitry Andric   if (Args.hasArg(OPT_verify))
2548461a67faSDimitry Andric     Opts.VerifyPrefixes.push_back("expected");
2549461a67faSDimitry Andric   // Keep VerifyPrefixes in its original order for the sake of diagnostics, and
2550461a67faSDimitry Andric   // then sort it to prepare for fast lookup using std::binary_search.
2551344a3780SDimitry Andric   if (!checkVerifyPrefixes(Opts.VerifyPrefixes, *Diags))
2552461a67faSDimitry Andric     Opts.VerifyDiagnostics = false;
2553461a67faSDimitry Andric   else
2554676fbe81SDimitry Andric     llvm::sort(Opts.VerifyPrefixes);
25552e645aa5SDimitry Andric   DiagnosticLevelMask DiagMask = DiagnosticLevelMask::None;
2556344a3780SDimitry Andric   parseDiagnosticLevelMask(
2557344a3780SDimitry Andric       "-verify-ignore-unexpected=",
2558344a3780SDimitry Andric       Args.getAllArgValues(OPT_verify_ignore_unexpected_EQ), *Diags, DiagMask);
25592e645aa5SDimitry Andric   if (Args.hasArg(OPT_verify_ignore_unexpected))
25602e645aa5SDimitry Andric     DiagMask = DiagnosticLevelMask::All;
25612e645aa5SDimitry Andric   Opts.setVerifyIgnoreUnexpected(DiagMask);
2562ee791ddeSRoman Divacky   if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) {
2563dbe13110SDimitry Andric     Diags->Report(diag::warn_ignoring_ftabstop_value)
2564dbe13110SDimitry Andric         << Opts.TabStop << DiagnosticOptions::DefaultTabStop;
25657fa27ce4SDimitry Andric     Opts.TabStop = DiagnosticOptions::DefaultTabStop;
2566ee791ddeSRoman Divacky   }
2567cfca06d7SDimitry Andric 
25689f4dbff6SDimitry Andric   addDiagnosticArgs(Args, OPT_W_Group, OPT_W_value_Group, Opts.Warnings);
25699f4dbff6SDimitry Andric   addDiagnosticArgs(Args, OPT_R_Group, OPT_R_value_Group, Opts.Remarks);
2570dbe13110SDimitry Andric 
2571344a3780SDimitry Andric   return Diags->getNumErrors() == NumErrorsBefore;
25721569ce68SRoman Divacky }
25731569ce68SRoman Divacky 
257445b53394SDimitry Andric /// Parse the argument to the -ftest-module-file-extension
257545b53394SDimitry Andric /// command-line argument.
257645b53394SDimitry Andric ///
257745b53394SDimitry Andric /// \returns true on error, false on success.
parseTestModuleFileExtensionArg(StringRef Arg,std::string & BlockName,unsigned & MajorVersion,unsigned & MinorVersion,bool & Hashed,std::string & UserInfo)257845b53394SDimitry Andric static bool parseTestModuleFileExtensionArg(StringRef Arg,
257945b53394SDimitry Andric                                             std::string &BlockName,
258045b53394SDimitry Andric                                             unsigned &MajorVersion,
258145b53394SDimitry Andric                                             unsigned &MinorVersion,
258245b53394SDimitry Andric                                             bool &Hashed,
258345b53394SDimitry Andric                                             std::string &UserInfo) {
258445b53394SDimitry Andric   SmallVector<StringRef, 5> Args;
258545b53394SDimitry Andric   Arg.split(Args, ':', 5);
258645b53394SDimitry Andric   if (Args.size() < 5)
258745b53394SDimitry Andric     return true;
258845b53394SDimitry Andric 
2589cfca06d7SDimitry Andric   BlockName = std::string(Args[0]);
259045b53394SDimitry Andric   if (Args[1].getAsInteger(10, MajorVersion)) return true;
259145b53394SDimitry Andric   if (Args[2].getAsInteger(10, MinorVersion)) return true;
259245b53394SDimitry Andric   if (Args[3].getAsInteger(2, Hashed)) return true;
259345b53394SDimitry Andric   if (Args.size() > 4)
2594cfca06d7SDimitry Andric     UserInfo = std::string(Args[4]);
259545b53394SDimitry Andric   return false;
259645b53394SDimitry Andric }
259745b53394SDimitry Andric 
2598344a3780SDimitry Andric /// Return a table that associates command line option specifiers with the
2599344a3780SDimitry Andric /// frontend action. Note: The pair {frontend::PluginAction, OPT_plugin} is
2600344a3780SDimitry Andric /// intentionally missing, as this case is handled separately from other
2601344a3780SDimitry Andric /// frontend options.
getFrontendActionTable()2602344a3780SDimitry Andric static const auto &getFrontendActionTable() {
2603344a3780SDimitry Andric   static const std::pair<frontend::ActionKind, unsigned> Table[] = {
2604344a3780SDimitry Andric       {frontend::ASTDeclList, OPT_ast_list},
2605344a3780SDimitry Andric 
2606344a3780SDimitry Andric       {frontend::ASTDump, OPT_ast_dump_all_EQ},
2607344a3780SDimitry Andric       {frontend::ASTDump, OPT_ast_dump_all},
2608344a3780SDimitry Andric       {frontend::ASTDump, OPT_ast_dump_EQ},
2609344a3780SDimitry Andric       {frontend::ASTDump, OPT_ast_dump},
2610344a3780SDimitry Andric       {frontend::ASTDump, OPT_ast_dump_lookups},
2611344a3780SDimitry Andric       {frontend::ASTDump, OPT_ast_dump_decl_types},
2612344a3780SDimitry Andric 
2613344a3780SDimitry Andric       {frontend::ASTPrint, OPT_ast_print},
2614344a3780SDimitry Andric       {frontend::ASTView, OPT_ast_view},
2615344a3780SDimitry Andric       {frontend::DumpCompilerOptions, OPT_compiler_options_dump},
2616344a3780SDimitry Andric       {frontend::DumpRawTokens, OPT_dump_raw_tokens},
2617344a3780SDimitry Andric       {frontend::DumpTokens, OPT_dump_tokens},
2618344a3780SDimitry Andric       {frontend::EmitAssembly, OPT_S},
2619344a3780SDimitry Andric       {frontend::EmitBC, OPT_emit_llvm_bc},
2620ac9a064cSDimitry Andric       {frontend::EmitCIR, OPT_emit_cir},
2621344a3780SDimitry Andric       {frontend::EmitHTML, OPT_emit_html},
2622344a3780SDimitry Andric       {frontend::EmitLLVM, OPT_emit_llvm},
2623344a3780SDimitry Andric       {frontend::EmitLLVMOnly, OPT_emit_llvm_only},
2624344a3780SDimitry Andric       {frontend::EmitCodeGenOnly, OPT_emit_codegen_only},
2625344a3780SDimitry Andric       {frontend::EmitObj, OPT_emit_obj},
26266f8fc217SDimitry Andric       {frontend::ExtractAPI, OPT_extract_api},
2627344a3780SDimitry Andric 
2628344a3780SDimitry Andric       {frontend::FixIt, OPT_fixit_EQ},
2629344a3780SDimitry Andric       {frontend::FixIt, OPT_fixit},
2630344a3780SDimitry Andric 
2631344a3780SDimitry Andric       {frontend::GenerateModule, OPT_emit_module},
2632344a3780SDimitry Andric       {frontend::GenerateModuleInterface, OPT_emit_module_interface},
2633ac9a064cSDimitry Andric       {frontend::GenerateReducedModuleInterface,
2634ac9a064cSDimitry Andric        OPT_emit_reduced_module_interface},
2635145449b1SDimitry Andric       {frontend::GenerateHeaderUnit, OPT_emit_header_unit},
2636344a3780SDimitry Andric       {frontend::GeneratePCH, OPT_emit_pch},
2637344a3780SDimitry Andric       {frontend::GenerateInterfaceStubs, OPT_emit_interface_stubs},
2638344a3780SDimitry Andric       {frontend::InitOnly, OPT_init_only},
2639344a3780SDimitry Andric       {frontend::ParseSyntaxOnly, OPT_fsyntax_only},
2640344a3780SDimitry Andric       {frontend::ModuleFileInfo, OPT_module_file_info},
2641344a3780SDimitry Andric       {frontend::VerifyPCH, OPT_verify_pch},
2642344a3780SDimitry Andric       {frontend::PrintPreamble, OPT_print_preamble},
2643344a3780SDimitry Andric       {frontend::PrintPreprocessedInput, OPT_E},
2644344a3780SDimitry Andric       {frontend::TemplightDump, OPT_templight_dump},
2645344a3780SDimitry Andric       {frontend::RewriteMacros, OPT_rewrite_macros},
2646344a3780SDimitry Andric       {frontend::RewriteObjC, OPT_rewrite_objc},
2647344a3780SDimitry Andric       {frontend::RewriteTest, OPT_rewrite_test},
2648344a3780SDimitry Andric       {frontend::RunAnalysis, OPT_analyze},
2649344a3780SDimitry Andric       {frontend::MigrateSource, OPT_migrate},
2650344a3780SDimitry Andric       {frontend::RunPreprocessorOnly, OPT_Eonly},
2651344a3780SDimitry Andric       {frontend::PrintDependencyDirectivesSourceMinimizerOutput,
2652344a3780SDimitry Andric        OPT_print_dependency_directives_minimized_source},
2653344a3780SDimitry Andric   };
2654344a3780SDimitry Andric 
2655344a3780SDimitry Andric   return Table;
2656344a3780SDimitry Andric }
2657344a3780SDimitry Andric 
2658344a3780SDimitry Andric /// Maps command line option to frontend action.
2659e3b55780SDimitry Andric static std::optional<frontend::ActionKind>
getFrontendAction(OptSpecifier & Opt)2660e3b55780SDimitry Andric getFrontendAction(OptSpecifier &Opt) {
2661344a3780SDimitry Andric   for (const auto &ActionOpt : getFrontendActionTable())
2662344a3780SDimitry Andric     if (ActionOpt.second == Opt.getID())
2663344a3780SDimitry Andric       return ActionOpt.first;
2664344a3780SDimitry Andric 
2665e3b55780SDimitry Andric   return std::nullopt;
2666344a3780SDimitry Andric }
2667344a3780SDimitry Andric 
2668344a3780SDimitry Andric /// Maps frontend action to command line option.
2669e3b55780SDimitry Andric static std::optional<OptSpecifier>
getProgramActionOpt(frontend::ActionKind ProgramAction)2670344a3780SDimitry Andric getProgramActionOpt(frontend::ActionKind ProgramAction) {
2671344a3780SDimitry Andric   for (const auto &ActionOpt : getFrontendActionTable())
2672344a3780SDimitry Andric     if (ActionOpt.first == ProgramAction)
2673344a3780SDimitry Andric       return OptSpecifier(ActionOpt.second);
2674344a3780SDimitry Andric 
2675e3b55780SDimitry Andric   return std::nullopt;
2676344a3780SDimitry Andric }
2677344a3780SDimitry Andric 
GenerateFrontendArgs(const FrontendOptions & Opts,ArgumentConsumer Consumer,bool IsHeader)2678344a3780SDimitry Andric static void GenerateFrontendArgs(const FrontendOptions &Opts,
2679b1c73532SDimitry Andric                                  ArgumentConsumer Consumer, bool IsHeader) {
2680344a3780SDimitry Andric   const FrontendOptions &FrontendOpts = Opts;
26817fa27ce4SDimitry Andric #define FRONTEND_OPTION_WITH_MARSHALLING(...)                                  \
2682b1c73532SDimitry Andric   GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
2683344a3780SDimitry Andric #include "clang/Driver/Options.inc"
2684344a3780SDimitry Andric #undef FRONTEND_OPTION_WITH_MARSHALLING
2685344a3780SDimitry Andric 
2686e3b55780SDimitry Andric   std::optional<OptSpecifier> ProgramActionOpt =
2687344a3780SDimitry Andric       getProgramActionOpt(Opts.ProgramAction);
2688344a3780SDimitry Andric 
2689344a3780SDimitry Andric   // Generating a simple flag covers most frontend actions.
2690344a3780SDimitry Andric   std::function<void()> GenerateProgramAction = [&]() {
2691b1c73532SDimitry Andric     GenerateArg(Consumer, *ProgramActionOpt);
2692344a3780SDimitry Andric   };
2693344a3780SDimitry Andric 
2694344a3780SDimitry Andric   if (!ProgramActionOpt) {
2695344a3780SDimitry Andric     // PluginAction is the only program action handled separately.
2696344a3780SDimitry Andric     assert(Opts.ProgramAction == frontend::PluginAction &&
2697344a3780SDimitry Andric            "Frontend action without option.");
2698344a3780SDimitry Andric     GenerateProgramAction = [&]() {
2699b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_plugin, Opts.ActionName);
2700344a3780SDimitry Andric     };
2701344a3780SDimitry Andric   }
2702344a3780SDimitry Andric 
2703344a3780SDimitry Andric   // FIXME: Simplify the complex 'AST dump' command line.
2704344a3780SDimitry Andric   if (Opts.ProgramAction == frontend::ASTDump) {
2705344a3780SDimitry Andric     GenerateProgramAction = [&]() {
2706344a3780SDimitry Andric       // ASTDumpLookups, ASTDumpDeclTypes and ASTDumpFilter are generated via
2707344a3780SDimitry Andric       // marshalling infrastructure.
2708344a3780SDimitry Andric 
2709344a3780SDimitry Andric       if (Opts.ASTDumpFormat != ADOF_Default) {
2710344a3780SDimitry Andric         StringRef Format;
2711344a3780SDimitry Andric         switch (Opts.ASTDumpFormat) {
2712344a3780SDimitry Andric         case ADOF_Default:
2713344a3780SDimitry Andric           llvm_unreachable("Default AST dump format.");
2714344a3780SDimitry Andric         case ADOF_JSON:
2715344a3780SDimitry Andric           Format = "json";
2716344a3780SDimitry Andric           break;
2717344a3780SDimitry Andric         }
2718344a3780SDimitry Andric 
2719344a3780SDimitry Andric         if (Opts.ASTDumpAll)
2720b1c73532SDimitry Andric           GenerateArg(Consumer, OPT_ast_dump_all_EQ, Format);
2721344a3780SDimitry Andric         if (Opts.ASTDumpDecls)
2722b1c73532SDimitry Andric           GenerateArg(Consumer, OPT_ast_dump_EQ, Format);
2723344a3780SDimitry Andric       } else {
2724344a3780SDimitry Andric         if (Opts.ASTDumpAll)
2725b1c73532SDimitry Andric           GenerateArg(Consumer, OPT_ast_dump_all);
2726344a3780SDimitry Andric         if (Opts.ASTDumpDecls)
2727b1c73532SDimitry Andric           GenerateArg(Consumer, OPT_ast_dump);
2728344a3780SDimitry Andric       }
2729344a3780SDimitry Andric     };
2730344a3780SDimitry Andric   }
2731344a3780SDimitry Andric 
2732344a3780SDimitry Andric   if (Opts.ProgramAction == frontend::FixIt && !Opts.FixItSuffix.empty()) {
2733344a3780SDimitry Andric     GenerateProgramAction = [&]() {
2734b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_fixit_EQ, Opts.FixItSuffix);
2735344a3780SDimitry Andric     };
2736344a3780SDimitry Andric   }
2737344a3780SDimitry Andric 
2738344a3780SDimitry Andric   GenerateProgramAction();
2739344a3780SDimitry Andric 
2740344a3780SDimitry Andric   for (const auto &PluginArgs : Opts.PluginArgs) {
2741344a3780SDimitry Andric     Option Opt = getDriverOptTable().getOption(OPT_plugin_arg);
2742344a3780SDimitry Andric     for (const auto &PluginArg : PluginArgs.second)
2743b1c73532SDimitry Andric       denormalizeString(Consumer,
2744b1c73532SDimitry Andric                         Opt.getPrefix() + Opt.getName() + PluginArgs.first,
2745b1c73532SDimitry Andric                         Opt.getKind(), 0, PluginArg);
2746344a3780SDimitry Andric   }
2747344a3780SDimitry Andric 
2748344a3780SDimitry Andric   for (const auto &Ext : Opts.ModuleFileExtensions)
2749344a3780SDimitry Andric     if (auto *TestExt = dyn_cast_or_null<TestModuleFileExtension>(Ext.get()))
2750b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_ftest_module_file_extension_EQ, TestExt->str());
2751344a3780SDimitry Andric 
2752344a3780SDimitry Andric   if (!Opts.CodeCompletionAt.FileName.empty())
2753b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_code_completion_at,
2754b1c73532SDimitry Andric                 Opts.CodeCompletionAt.ToString());
2755344a3780SDimitry Andric 
2756344a3780SDimitry Andric   for (const auto &Plugin : Opts.Plugins)
2757b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_load, Plugin);
2758344a3780SDimitry Andric 
2759344a3780SDimitry Andric   // ASTDumpDecls and ASTDumpAll already handled with ProgramAction.
2760344a3780SDimitry Andric 
2761344a3780SDimitry Andric   for (const auto &ModuleFile : Opts.ModuleFiles)
2762b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fmodule_file, ModuleFile);
2763344a3780SDimitry Andric 
2764145449b1SDimitry Andric   if (Opts.AuxTargetCPU)
2765b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_aux_target_cpu, *Opts.AuxTargetCPU);
2766344a3780SDimitry Andric 
2767145449b1SDimitry Andric   if (Opts.AuxTargetFeatures)
2768344a3780SDimitry Andric     for (const auto &Feature : *Opts.AuxTargetFeatures)
2769b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_aux_target_feature, Feature);
2770344a3780SDimitry Andric 
2771344a3780SDimitry Andric   {
2772344a3780SDimitry Andric     StringRef Preprocessed = Opts.DashX.isPreprocessed() ? "-cpp-output" : "";
2773344a3780SDimitry Andric     StringRef ModuleMap =
2774344a3780SDimitry Andric         Opts.DashX.getFormat() == InputKind::ModuleMap ? "-module-map" : "";
2775145449b1SDimitry Andric     StringRef HeaderUnit = "";
2776145449b1SDimitry Andric     switch (Opts.DashX.getHeaderUnitKind()) {
2777145449b1SDimitry Andric     case InputKind::HeaderUnit_None:
2778145449b1SDimitry Andric       break;
2779145449b1SDimitry Andric     case InputKind::HeaderUnit_User:
2780145449b1SDimitry Andric       HeaderUnit = "-user";
2781145449b1SDimitry Andric       break;
2782145449b1SDimitry Andric     case InputKind::HeaderUnit_System:
2783145449b1SDimitry Andric       HeaderUnit = "-system";
2784145449b1SDimitry Andric       break;
2785145449b1SDimitry Andric     case InputKind::HeaderUnit_Abs:
2786145449b1SDimitry Andric       HeaderUnit = "-header-unit";
2787145449b1SDimitry Andric       break;
2788145449b1SDimitry Andric     }
2789344a3780SDimitry Andric     StringRef Header = IsHeader ? "-header" : "";
2790344a3780SDimitry Andric 
2791344a3780SDimitry Andric     StringRef Lang;
2792344a3780SDimitry Andric     switch (Opts.DashX.getLanguage()) {
2793344a3780SDimitry Andric     case Language::C:
2794344a3780SDimitry Andric       Lang = "c";
2795344a3780SDimitry Andric       break;
2796344a3780SDimitry Andric     case Language::OpenCL:
2797344a3780SDimitry Andric       Lang = "cl";
2798344a3780SDimitry Andric       break;
2799344a3780SDimitry Andric     case Language::OpenCLCXX:
2800344a3780SDimitry Andric       Lang = "clcpp";
2801344a3780SDimitry Andric       break;
2802344a3780SDimitry Andric     case Language::CUDA:
2803344a3780SDimitry Andric       Lang = "cuda";
2804344a3780SDimitry Andric       break;
2805344a3780SDimitry Andric     case Language::HIP:
2806344a3780SDimitry Andric       Lang = "hip";
2807344a3780SDimitry Andric       break;
2808344a3780SDimitry Andric     case Language::CXX:
2809344a3780SDimitry Andric       Lang = "c++";
2810344a3780SDimitry Andric       break;
2811344a3780SDimitry Andric     case Language::ObjC:
2812344a3780SDimitry Andric       Lang = "objective-c";
2813344a3780SDimitry Andric       break;
2814344a3780SDimitry Andric     case Language::ObjCXX:
2815344a3780SDimitry Andric       Lang = "objective-c++";
2816344a3780SDimitry Andric       break;
2817344a3780SDimitry Andric     case Language::RenderScript:
2818344a3780SDimitry Andric       Lang = "renderscript";
2819344a3780SDimitry Andric       break;
2820344a3780SDimitry Andric     case Language::Asm:
2821344a3780SDimitry Andric       Lang = "assembler-with-cpp";
2822344a3780SDimitry Andric       break;
2823344a3780SDimitry Andric     case Language::Unknown:
2824344a3780SDimitry Andric       assert(Opts.DashX.getFormat() == InputKind::Precompiled &&
2825344a3780SDimitry Andric              "Generating -x argument for unknown language (not precompiled).");
2826344a3780SDimitry Andric       Lang = "ast";
2827344a3780SDimitry Andric       break;
2828344a3780SDimitry Andric     case Language::LLVM_IR:
2829344a3780SDimitry Andric       Lang = "ir";
2830344a3780SDimitry Andric       break;
2831145449b1SDimitry Andric     case Language::HLSL:
2832145449b1SDimitry Andric       Lang = "hlsl";
2833145449b1SDimitry Andric       break;
2834ac9a064cSDimitry Andric     case Language::CIR:
2835ac9a064cSDimitry Andric       Lang = "cir";
2836ac9a064cSDimitry Andric       break;
2837344a3780SDimitry Andric     }
2838344a3780SDimitry Andric 
2839b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_x,
2840b1c73532SDimitry Andric                 Lang + HeaderUnit + Header + ModuleMap + Preprocessed);
2841344a3780SDimitry Andric   }
2842344a3780SDimitry Andric 
2843344a3780SDimitry Andric   // OPT_INPUT has a unique class, generate it directly.
2844344a3780SDimitry Andric   for (const auto &Input : Opts.Inputs)
2845b1c73532SDimitry Andric     Consumer(Input.getFile());
2846344a3780SDimitry Andric }
2847344a3780SDimitry Andric 
ParseFrontendArgs(FrontendOptions & Opts,ArgList & Args,DiagnosticsEngine & Diags,bool & IsHeaderFile)2848344a3780SDimitry Andric static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
2849344a3780SDimitry Andric                               DiagnosticsEngine &Diags, bool &IsHeaderFile) {
2850344a3780SDimitry Andric   unsigned NumErrorsBefore = Diags.getNumErrors();
2851344a3780SDimitry Andric 
2852344a3780SDimitry Andric   FrontendOptions &FrontendOpts = Opts;
2853344a3780SDimitry Andric 
28547fa27ce4SDimitry Andric #define FRONTEND_OPTION_WITH_MARSHALLING(...)                                  \
28557fa27ce4SDimitry Andric   PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
2856344a3780SDimitry Andric #include "clang/Driver/Options.inc"
2857344a3780SDimitry Andric #undef FRONTEND_OPTION_WITH_MARSHALLING
2858344a3780SDimitry Andric 
28591569ce68SRoman Divacky   Opts.ProgramAction = frontend::ParseSyntaxOnly;
28601569ce68SRoman Divacky   if (const Arg *A = Args.getLastArg(OPT_Action_Group)) {
2861344a3780SDimitry Andric     OptSpecifier Opt = OptSpecifier(A->getOption().getID());
2862e3b55780SDimitry Andric     std::optional<frontend::ActionKind> ProgramAction = getFrontendAction(Opt);
2863344a3780SDimitry Andric     assert(ProgramAction && "Option specifier not in Action_Group.");
2864344a3780SDimitry Andric 
2865344a3780SDimitry Andric     if (ProgramAction == frontend::ASTDump &&
2866344a3780SDimitry Andric         (Opt == OPT_ast_dump_all_EQ || Opt == OPT_ast_dump_EQ)) {
286722989816SDimitry Andric       unsigned Val = llvm::StringSwitch<unsigned>(A->getValue())
286822989816SDimitry Andric                          .CaseLower("default", ADOF_Default)
286922989816SDimitry Andric                          .CaseLower("json", ADOF_JSON)
287022989816SDimitry Andric                          .Default(std::numeric_limits<unsigned>::max());
287122989816SDimitry Andric 
287222989816SDimitry Andric       if (Val != std::numeric_limits<unsigned>::max())
287322989816SDimitry Andric         Opts.ASTDumpFormat = static_cast<ASTDumpOutputFormat>(Val);
287422989816SDimitry Andric       else {
287522989816SDimitry Andric         Diags.Report(diag::err_drv_invalid_value)
287622989816SDimitry Andric             << A->getAsString(Args) << A->getValue();
287722989816SDimitry Andric         Opts.ASTDumpFormat = ADOF_Default;
287822989816SDimitry Andric       }
287922989816SDimitry Andric     }
2880344a3780SDimitry Andric 
2881344a3780SDimitry Andric     if (ProgramAction == frontend::FixIt && Opt == OPT_fixit_EQ)
288213cc256eSDimitry Andric       Opts.FixItSuffix = A->getValue();
2883344a3780SDimitry Andric 
2884344a3780SDimitry Andric     if (ProgramAction == frontend::GenerateInterfaceStubs) {
2885519fc96cSDimitry Andric       StringRef ArgStr =
2886519fc96cSDimitry Andric           Args.hasArg(OPT_interface_stub_version_EQ)
2887519fc96cSDimitry Andric               ? Args.getLastArgValue(OPT_interface_stub_version_EQ)
2888344a3780SDimitry Andric               : "ifs-v1";
2889519fc96cSDimitry Andric       if (ArgStr == "experimental-yaml-elf-v1" ||
2890344a3780SDimitry Andric           ArgStr == "experimental-ifs-v1" || ArgStr == "experimental-ifs-v2" ||
2891519fc96cSDimitry Andric           ArgStr == "experimental-tapi-elf-v1") {
2892519fc96cSDimitry Andric         std::string ErrorMessage =
2893519fc96cSDimitry Andric             "Invalid interface stub format: " + ArgStr.str() +
2894519fc96cSDimitry Andric             " is deprecated.";
289522989816SDimitry Andric         Diags.Report(diag::err_drv_invalid_value)
2896519fc96cSDimitry Andric             << "Must specify a valid interface stub format type, ie: "
2897344a3780SDimitry Andric                "-interface-stub-version=ifs-v1"
2898519fc96cSDimitry Andric             << ErrorMessage;
2899344a3780SDimitry Andric         ProgramAction = frontend::ParseSyntaxOnly;
2900312c0ed1SDimitry Andric       } else if (!ArgStr.starts_with("ifs-")) {
2901519fc96cSDimitry Andric         std::string ErrorMessage =
2902519fc96cSDimitry Andric             "Invalid interface stub format: " + ArgStr.str() + ".";
2903519fc96cSDimitry Andric         Diags.Report(diag::err_drv_invalid_value)
2904519fc96cSDimitry Andric             << "Must specify a valid interface stub format type, ie: "
2905344a3780SDimitry Andric                "-interface-stub-version=ifs-v1"
2906519fc96cSDimitry Andric             << ErrorMessage;
2907344a3780SDimitry Andric         ProgramAction = frontend::ParseSyntaxOnly;
2908519fc96cSDimitry Andric       }
290922989816SDimitry Andric     }
2910344a3780SDimitry Andric 
2911344a3780SDimitry Andric     Opts.ProgramAction = *ProgramAction;
2912ac9a064cSDimitry Andric 
2913ac9a064cSDimitry Andric     // Catch common mistakes when multiple actions are specified for cc1 (e.g.
2914ac9a064cSDimitry Andric     // -S -emit-llvm means -emit-llvm while -emit-llvm -S means -S). However, to
2915ac9a064cSDimitry Andric     // support driver `-c -Xclang ACTION` (-cc1 -emit-llvm file -main-file-name
2916ac9a064cSDimitry Andric     // X ACTION), we suppress the error when the two actions are separated by
2917ac9a064cSDimitry Andric     // -main-file-name.
2918ac9a064cSDimitry Andric     //
2919ac9a064cSDimitry Andric     // As an exception, accept composable -ast-dump*.
2920ac9a064cSDimitry Andric     if (!A->getSpelling().starts_with("-ast-dump")) {
2921ac9a064cSDimitry Andric       const Arg *SavedAction = nullptr;
2922ac9a064cSDimitry Andric       for (const Arg *AA :
2923ac9a064cSDimitry Andric            Args.filtered(OPT_Action_Group, OPT_main_file_name)) {
2924ac9a064cSDimitry Andric         if (AA->getOption().matches(OPT_main_file_name)) {
2925ac9a064cSDimitry Andric           SavedAction = nullptr;
2926ac9a064cSDimitry Andric         } else if (!SavedAction) {
2927ac9a064cSDimitry Andric           SavedAction = AA;
2928ac9a064cSDimitry Andric         } else {
2929ac9a064cSDimitry Andric           if (!A->getOption().matches(OPT_ast_dump_EQ))
2930ac9a064cSDimitry Andric             Diags.Report(diag::err_fe_invalid_multiple_actions)
2931ac9a064cSDimitry Andric                 << SavedAction->getSpelling() << A->getSpelling();
2932ac9a064cSDimitry Andric           break;
2933ac9a064cSDimitry Andric         }
2934ac9a064cSDimitry Andric       }
2935ac9a064cSDimitry Andric     }
29361569ce68SRoman Divacky   }
29374ba67500SRoman Divacky 
29381569ce68SRoman Divacky   if (const Arg* A = Args.getLastArg(OPT_plugin)) {
2939798321d8SDimitry Andric     Opts.Plugins.emplace_back(A->getValue(0));
29401569ce68SRoman Divacky     Opts.ProgramAction = frontend::PluginAction;
294113cc256eSDimitry Andric     Opts.ActionName = A->getValue();
29421569ce68SRoman Divacky   }
294348675466SDimitry Andric   for (const auto *AA : Args.filtered(OPT_plugin_arg))
29442b6b257fSDimitry Andric     Opts.PluginArgs[AA->getValue(0)].emplace_back(AA->getValue(1));
2945bca07a45SDimitry Andric 
294645b53394SDimitry Andric   for (const std::string &Arg :
294745b53394SDimitry Andric          Args.getAllArgValues(OPT_ftest_module_file_extension_EQ)) {
294845b53394SDimitry Andric     std::string BlockName;
294945b53394SDimitry Andric     unsigned MajorVersion;
295045b53394SDimitry Andric     unsigned MinorVersion;
295145b53394SDimitry Andric     bool Hashed;
295245b53394SDimitry Andric     std::string UserInfo;
295345b53394SDimitry Andric     if (parseTestModuleFileExtensionArg(Arg, BlockName, MajorVersion,
295445b53394SDimitry Andric                                         MinorVersion, Hashed, UserInfo)) {
295545b53394SDimitry Andric       Diags.Report(diag::err_test_module_file_extension_format) << Arg;
295645b53394SDimitry Andric 
295745b53394SDimitry Andric       continue;
295845b53394SDimitry Andric     }
295945b53394SDimitry Andric 
296045b53394SDimitry Andric     // Add the testing module file extension.
296145b53394SDimitry Andric     Opts.ModuleFileExtensions.push_back(
29626694ed09SDimitry Andric         std::make_shared<TestModuleFileExtension>(
29636694ed09SDimitry Andric             BlockName, MajorVersion, MinorVersion, Hashed, UserInfo));
296445b53394SDimitry Andric   }
296545b53394SDimitry Andric 
29661569ce68SRoman Divacky   if (const Arg *A = Args.getLastArg(OPT_code_completion_at)) {
29671569ce68SRoman Divacky     Opts.CodeCompletionAt =
296813cc256eSDimitry Andric       ParsedSourceLocation::FromString(A->getValue());
29691569ce68SRoman Divacky     if (Opts.CodeCompletionAt.FileName.empty())
29701569ce68SRoman Divacky       Diags.Report(diag::err_drv_invalid_value)
297113cc256eSDimitry Andric         << A->getAsString(Args) << A->getValue();
29721569ce68SRoman Divacky   }
29731569ce68SRoman Divacky 
2974d7279c4cSRoman Divacky   Opts.Plugins = Args.getAllArgValues(OPT_load);
297522989816SDimitry Andric   Opts.ASTDumpDecls = Args.hasArg(OPT_ast_dump, OPT_ast_dump_EQ);
297622989816SDimitry Andric   Opts.ASTDumpAll = Args.hasArg(OPT_ast_dump_all, OPT_ast_dump_all_EQ);
2977461a67faSDimitry Andric   // Only the -fmodule-file=<file> form.
297848675466SDimitry Andric   for (const auto *A : Args.filtered(OPT_fmodule_file)) {
2979461a67faSDimitry Andric     StringRef Val = A->getValue();
2980c0981da4SDimitry Andric     if (!Val.contains('='))
2981cfca06d7SDimitry Andric       Opts.ModuleFiles.push_back(std::string(Val));
2982461a67faSDimitry Andric   }
2983cfca06d7SDimitry Andric 
2984cfca06d7SDimitry Andric   if (Opts.ProgramAction != frontend::GenerateModule && Opts.IsSystemModule)
2985cfca06d7SDimitry Andric     Diags.Report(diag::err_drv_argument_only_allowed_with) << "-fsystem-module"
2986cfca06d7SDimitry Andric                                                            << "-emit-module";
2987ac9a064cSDimitry Andric   if (Args.hasArg(OPT_fclangir) || Args.hasArg(OPT_emit_cir))
2988ac9a064cSDimitry Andric     Opts.UseClangIRPipeline = true;
298956d91b49SDimitry Andric 
2990cfca06d7SDimitry Andric   if (Args.hasArg(OPT_aux_target_cpu))
2991cfca06d7SDimitry Andric     Opts.AuxTargetCPU = std::string(Args.getLastArgValue(OPT_aux_target_cpu));
2992cfca06d7SDimitry Andric   if (Args.hasArg(OPT_aux_target_feature))
2993cfca06d7SDimitry Andric     Opts.AuxTargetFeatures = Args.getAllArgValues(OPT_aux_target_feature);
2994dbe13110SDimitry Andric 
2995dbe13110SDimitry Andric   if (Opts.ARCMTAction != FrontendOptions::ARCMT_None &&
2996dbe13110SDimitry Andric       Opts.ObjCMTAction != FrontendOptions::ObjCMT_None) {
2997dbe13110SDimitry Andric     Diags.Report(diag::err_drv_argument_not_allowed_with)
2998dbe13110SDimitry Andric       << "ARC migration" << "ObjC migration";
2999dbe13110SDimitry Andric   }
3000dbe13110SDimitry Andric 
3001519fc96cSDimitry Andric   InputKind DashX(Language::Unknown);
30021569ce68SRoman Divacky   if (const Arg *A = Args.getLastArg(OPT_x)) {
300357091882SDimitry Andric     StringRef XValue = A->getValue();
300457091882SDimitry Andric 
3005145449b1SDimitry Andric     // Parse suffixes:
3006145449b1SDimitry Andric     // '<lang>(-[{header-unit,user,system}-]header|[-module-map][-cpp-output])'.
300757091882SDimitry Andric     // FIXME: Supporting '<lang>-header-cpp-output' would be useful.
300857091882SDimitry Andric     bool Preprocessed = XValue.consume_back("-cpp-output");
300957091882SDimitry Andric     bool ModuleMap = XValue.consume_back("-module-map");
3010145449b1SDimitry Andric     // Detect and consume the header indicator.
3011145449b1SDimitry Andric     bool IsHeader =
3012145449b1SDimitry Andric         XValue != "precompiled-header" && XValue.consume_back("-header");
3013145449b1SDimitry Andric 
3014145449b1SDimitry Andric     // If we have c++-{user,system}-header, that indicates a header unit input
3015145449b1SDimitry Andric     // likewise, if the user put -fmodule-header together with a header with an
3016145449b1SDimitry Andric     // absolute path (header-unit-header).
3017145449b1SDimitry Andric     InputKind::HeaderUnitKind HUK = InputKind::HeaderUnit_None;
3018145449b1SDimitry Andric     if (IsHeader || Preprocessed) {
3019145449b1SDimitry Andric       if (XValue.consume_back("-header-unit"))
3020145449b1SDimitry Andric         HUK = InputKind::HeaderUnit_Abs;
3021145449b1SDimitry Andric       else if (XValue.consume_back("-system"))
3022145449b1SDimitry Andric         HUK = InputKind::HeaderUnit_System;
3023145449b1SDimitry Andric       else if (XValue.consume_back("-user"))
3024145449b1SDimitry Andric         HUK = InputKind::HeaderUnit_User;
3025145449b1SDimitry Andric     }
3026145449b1SDimitry Andric 
3027145449b1SDimitry Andric     // The value set by this processing is an un-preprocessed source which is
3028145449b1SDimitry Andric     // not intended to be a module map or header unit.
3029145449b1SDimitry Andric     IsHeaderFile = IsHeader && !Preprocessed && !ModuleMap &&
3030145449b1SDimitry Andric                    HUK == InputKind::HeaderUnit_None;
303157091882SDimitry Andric 
303257091882SDimitry Andric     // Principal languages.
303357091882SDimitry Andric     DashX = llvm::StringSwitch<InputKind>(XValue)
3034519fc96cSDimitry Andric                 .Case("c", Language::C)
3035519fc96cSDimitry Andric                 .Case("cl", Language::OpenCL)
3036344a3780SDimitry Andric                 .Case("clcpp", Language::OpenCLCXX)
3037519fc96cSDimitry Andric                 .Case("cuda", Language::CUDA)
3038519fc96cSDimitry Andric                 .Case("hip", Language::HIP)
3039519fc96cSDimitry Andric                 .Case("c++", Language::CXX)
3040519fc96cSDimitry Andric                 .Case("objective-c", Language::ObjC)
3041519fc96cSDimitry Andric                 .Case("objective-c++", Language::ObjCXX)
3042519fc96cSDimitry Andric                 .Case("renderscript", Language::RenderScript)
3043145449b1SDimitry Andric                 .Case("hlsl", Language::HLSL)
3044519fc96cSDimitry Andric                 .Default(Language::Unknown);
304557091882SDimitry Andric 
304657091882SDimitry Andric     // "objc[++]-cpp-output" is an acceptable synonym for
304757091882SDimitry Andric     // "objective-c[++]-cpp-output".
3048145449b1SDimitry Andric     if (DashX.isUnknown() && Preprocessed && !IsHeaderFile && !ModuleMap &&
3049145449b1SDimitry Andric         HUK == InputKind::HeaderUnit_None)
305057091882SDimitry Andric       DashX = llvm::StringSwitch<InputKind>(XValue)
3051519fc96cSDimitry Andric                   .Case("objc", Language::ObjC)
3052519fc96cSDimitry Andric                   .Case("objc++", Language::ObjCXX)
3053519fc96cSDimitry Andric                   .Default(Language::Unknown);
305457091882SDimitry Andric 
305557091882SDimitry Andric     // Some special cases cannot be combined with suffixes.
3056145449b1SDimitry Andric     if (DashX.isUnknown() && !Preprocessed && !IsHeaderFile && !ModuleMap &&
3057145449b1SDimitry Andric         HUK == InputKind::HeaderUnit_None)
305857091882SDimitry Andric       DashX = llvm::StringSwitch<InputKind>(XValue)
3059519fc96cSDimitry Andric                   .Case("cpp-output", InputKind(Language::C).getPreprocessed())
3060519fc96cSDimitry Andric                   .Case("assembler-with-cpp", Language::Asm)
3061b60736ecSDimitry Andric                   .Cases("ast", "pcm", "precompiled-header",
3062519fc96cSDimitry Andric                          InputKind(Language::Unknown, InputKind::Precompiled))
3063519fc96cSDimitry Andric                   .Case("ir", Language::LLVM_IR)
3064ac9a064cSDimitry Andric                   .Case("cir", Language::CIR)
3065519fc96cSDimitry Andric                   .Default(Language::Unknown);
306657091882SDimitry Andric 
306757091882SDimitry Andric     if (DashX.isUnknown())
30681569ce68SRoman Divacky       Diags.Report(diag::err_drv_invalid_value)
306913cc256eSDimitry Andric         << A->getAsString(Args) << A->getValue();
307057091882SDimitry Andric 
307157091882SDimitry Andric     if (Preprocessed)
307257091882SDimitry Andric       DashX = DashX.getPreprocessed();
3073145449b1SDimitry Andric     // A regular header is considered mutually exclusive with a header unit.
3074145449b1SDimitry Andric     if (HUK != InputKind::HeaderUnit_None) {
3075145449b1SDimitry Andric       DashX = DashX.withHeaderUnit(HUK);
3076145449b1SDimitry Andric       IsHeaderFile = true;
3077145449b1SDimitry Andric     } else if (IsHeaderFile)
3078145449b1SDimitry Andric       DashX = DashX.getHeader();
307957091882SDimitry Andric     if (ModuleMap)
308057091882SDimitry Andric       DashX = DashX.withFormat(InputKind::ModuleMap);
30811569ce68SRoman Divacky   }
30821569ce68SRoman Divacky 
30831569ce68SRoman Divacky   // '-' is the default input if none is given.
3084d7279c4cSRoman Divacky   std::vector<std::string> Inputs = Args.getAllArgValues(OPT_INPUT);
30851569ce68SRoman Divacky   Opts.Inputs.clear();
30861569ce68SRoman Divacky   if (Inputs.empty())
30871569ce68SRoman Divacky     Inputs.push_back("-");
3088145449b1SDimitry Andric 
3089145449b1SDimitry Andric   if (DashX.getHeaderUnitKind() != InputKind::HeaderUnit_None &&
3090145449b1SDimitry Andric       Inputs.size() > 1)
3091145449b1SDimitry Andric     Diags.Report(diag::err_drv_header_unit_extra_inputs) << Inputs[1];
3092145449b1SDimitry Andric 
30931569ce68SRoman Divacky   for (unsigned i = 0, e = Inputs.size(); i != e; ++i) {
30944ba67500SRoman Divacky     InputKind IK = DashX;
309557091882SDimitry Andric     if (IK.isUnknown()) {
30961569ce68SRoman Divacky       IK = FrontendOptions::getInputKindForExtension(
309736981b17SDimitry Andric         StringRef(Inputs[i]).rsplit('.').second);
309857091882SDimitry Andric       // FIXME: Warn on this?
309957091882SDimitry Andric       if (IK.isUnknown())
3100519fc96cSDimitry Andric         IK = Language::C;
31011569ce68SRoman Divacky       // FIXME: Remove this hack.
31021569ce68SRoman Divacky       if (i == 0)
31031569ce68SRoman Divacky         DashX = IK;
31041569ce68SRoman Divacky     }
310557091882SDimitry Andric 
3106cfca06d7SDimitry Andric     bool IsSystem = false;
3107cfca06d7SDimitry Andric 
310857091882SDimitry Andric     // The -emit-module action implicitly takes a module map.
310957091882SDimitry Andric     if (Opts.ProgramAction == frontend::GenerateModule &&
3110cfca06d7SDimitry Andric         IK.getFormat() == InputKind::Source) {
311157091882SDimitry Andric       IK = IK.withFormat(InputKind::ModuleMap);
3112cfca06d7SDimitry Andric       IsSystem = Opts.IsSystemModule;
3113cfca06d7SDimitry Andric     }
311457091882SDimitry Andric 
3115cfca06d7SDimitry Andric     Opts.Inputs.emplace_back(std::move(Inputs[i]), IK, IsSystem);
31161569ce68SRoman Divacky   }
31171569ce68SRoman Divacky 
3118344a3780SDimitry Andric   Opts.DashX = DashX;
3119344a3780SDimitry Andric 
3120344a3780SDimitry Andric   return Diags.getNumErrors() == NumErrorsBefore;
31211569ce68SRoman Divacky }
31221569ce68SRoman Divacky 
GetResourcesPath(const char * Argv0,void * MainAddr)312334d02d0bSRoman Divacky std::string CompilerInvocation::GetResourcesPath(const char *Argv0,
31241569ce68SRoman Divacky                                                  void *MainAddr) {
312506d4ba38SDimitry Andric   std::string ClangExecutable =
312606d4ba38SDimitry Andric       llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
312722989816SDimitry Andric   return Driver::GetResourcesPath(ClangExecutable, CLANG_RESOURCE_DIR);
31281569ce68SRoman Divacky }
31291569ce68SRoman Divacky 
GenerateHeaderSearchArgs(const HeaderSearchOptions & Opts,ArgumentConsumer Consumer)3130b1c73532SDimitry Andric static void GenerateHeaderSearchArgs(const HeaderSearchOptions &Opts,
3131b1c73532SDimitry Andric                                      ArgumentConsumer Consumer) {
3132344a3780SDimitry Andric   const HeaderSearchOptions *HeaderSearchOpts = &Opts;
31337fa27ce4SDimitry Andric #define HEADER_SEARCH_OPTION_WITH_MARSHALLING(...)                             \
3134b1c73532SDimitry Andric   GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
3135344a3780SDimitry Andric #include "clang/Driver/Options.inc"
3136344a3780SDimitry Andric #undef HEADER_SEARCH_OPTION_WITH_MARSHALLING
3137344a3780SDimitry Andric 
3138344a3780SDimitry Andric   if (Opts.UseLibcxx)
3139b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_stdlib_EQ, "libc++");
3140344a3780SDimitry Andric 
3141344a3780SDimitry Andric   if (!Opts.ModuleCachePath.empty())
3142b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fmodules_cache_path, Opts.ModuleCachePath);
3143344a3780SDimitry Andric 
3144344a3780SDimitry Andric   for (const auto &File : Opts.PrebuiltModuleFiles)
3145b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fmodule_file, File.first + "=" + File.second);
3146344a3780SDimitry Andric 
3147344a3780SDimitry Andric   for (const auto &Path : Opts.PrebuiltModulePaths)
3148b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fprebuilt_module_path, Path);
3149344a3780SDimitry Andric 
3150344a3780SDimitry Andric   for (const auto &Macro : Opts.ModulesIgnoreMacros)
3151b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fmodules_ignore_macro, Macro.val());
3152344a3780SDimitry Andric 
3153344a3780SDimitry Andric   auto Matches = [](const HeaderSearchOptions::Entry &Entry,
3154344a3780SDimitry Andric                     llvm::ArrayRef<frontend::IncludeDirGroup> Groups,
3155e3b55780SDimitry Andric                     std::optional<bool> IsFramework,
3156e3b55780SDimitry Andric                     std::optional<bool> IgnoreSysRoot) {
3157c0981da4SDimitry Andric     return llvm::is_contained(Groups, Entry.Group) &&
3158344a3780SDimitry Andric            (!IsFramework || (Entry.IsFramework == *IsFramework)) &&
3159344a3780SDimitry Andric            (!IgnoreSysRoot || (Entry.IgnoreSysRoot == *IgnoreSysRoot));
3160344a3780SDimitry Andric   };
3161344a3780SDimitry Andric 
3162344a3780SDimitry Andric   auto It = Opts.UserEntries.begin();
3163344a3780SDimitry Andric   auto End = Opts.UserEntries.end();
3164344a3780SDimitry Andric 
3165344a3780SDimitry Andric   // Add -I..., -F..., and -index-header-map options in order.
3166e3b55780SDimitry Andric   for (; It < End && Matches(*It, {frontend::IndexHeaderMap, frontend::Angled},
3167e3b55780SDimitry Andric                              std::nullopt, true);
3168344a3780SDimitry Andric        ++It) {
3169344a3780SDimitry Andric     OptSpecifier Opt = [It, Matches]() {
3170344a3780SDimitry Andric       if (Matches(*It, frontend::IndexHeaderMap, true, true))
3171344a3780SDimitry Andric         return OPT_F;
3172344a3780SDimitry Andric       if (Matches(*It, frontend::IndexHeaderMap, false, true))
3173344a3780SDimitry Andric         return OPT_I;
3174344a3780SDimitry Andric       if (Matches(*It, frontend::Angled, true, true))
3175344a3780SDimitry Andric         return OPT_F;
3176344a3780SDimitry Andric       if (Matches(*It, frontend::Angled, false, true))
3177344a3780SDimitry Andric         return OPT_I;
3178344a3780SDimitry Andric       llvm_unreachable("Unexpected HeaderSearchOptions::Entry.");
3179344a3780SDimitry Andric     }();
3180344a3780SDimitry Andric 
3181344a3780SDimitry Andric     if (It->Group == frontend::IndexHeaderMap)
3182b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_index_header_map);
3183b1c73532SDimitry Andric     GenerateArg(Consumer, Opt, It->Path);
3184344a3780SDimitry Andric   };
3185344a3780SDimitry Andric 
3186344a3780SDimitry Andric   // Note: some paths that came from "[-iprefix=xx] -iwithprefixbefore=yy" may
3187344a3780SDimitry Andric   // have already been generated as "-I[xx]yy". If that's the case, their
3188344a3780SDimitry Andric   // position on command line was such that this has no semantic impact on
3189344a3780SDimitry Andric   // include paths.
3190344a3780SDimitry Andric   for (; It < End &&
3191344a3780SDimitry Andric          Matches(*It, {frontend::After, frontend::Angled}, false, true);
3192344a3780SDimitry Andric        ++It) {
3193344a3780SDimitry Andric     OptSpecifier Opt =
3194344a3780SDimitry Andric         It->Group == frontend::After ? OPT_iwithprefix : OPT_iwithprefixbefore;
3195b1c73532SDimitry Andric     GenerateArg(Consumer, Opt, It->Path);
3196344a3780SDimitry Andric   }
3197344a3780SDimitry Andric 
3198344a3780SDimitry Andric   // Note: Some paths that came from "-idirafter=xxyy" may have already been
3199344a3780SDimitry Andric   // generated as "-iwithprefix=xxyy". If that's the case, their position on
3200344a3780SDimitry Andric   // command line was such that this has no semantic impact on include paths.
3201344a3780SDimitry Andric   for (; It < End && Matches(*It, {frontend::After}, false, true); ++It)
3202b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_idirafter, It->Path);
3203344a3780SDimitry Andric   for (; It < End && Matches(*It, {frontend::Quoted}, false, true); ++It)
3204b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_iquote, It->Path);
3205e3b55780SDimitry Andric   for (; It < End && Matches(*It, {frontend::System}, false, std::nullopt);
3206e3b55780SDimitry Andric        ++It)
3207b1c73532SDimitry Andric     GenerateArg(Consumer, It->IgnoreSysRoot ? OPT_isystem : OPT_iwithsysroot,
3208b1c73532SDimitry Andric                 It->Path);
3209344a3780SDimitry Andric   for (; It < End && Matches(*It, {frontend::System}, true, true); ++It)
3210b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_iframework, It->Path);
3211344a3780SDimitry Andric   for (; It < End && Matches(*It, {frontend::System}, true, false); ++It)
3212b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_iframeworkwithsysroot, It->Path);
3213344a3780SDimitry Andric 
3214344a3780SDimitry Andric   // Add the paths for the various language specific isystem flags.
3215344a3780SDimitry Andric   for (; It < End && Matches(*It, {frontend::CSystem}, false, true); ++It)
3216b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_c_isystem, It->Path);
3217344a3780SDimitry Andric   for (; It < End && Matches(*It, {frontend::CXXSystem}, false, true); ++It)
3218b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_cxx_isystem, It->Path);
3219344a3780SDimitry Andric   for (; It < End && Matches(*It, {frontend::ObjCSystem}, false, true); ++It)
3220b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_objc_isystem, It->Path);
3221344a3780SDimitry Andric   for (; It < End && Matches(*It, {frontend::ObjCXXSystem}, false, true); ++It)
3222b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_objcxx_isystem, It->Path);
3223344a3780SDimitry Andric 
3224344a3780SDimitry Andric   // Add the internal paths from a driver that detects standard include paths.
3225344a3780SDimitry Andric   // Note: Some paths that came from "-internal-isystem" arguments may have
3226344a3780SDimitry Andric   // already been generated as "-isystem". If that's the case, their position on
3227344a3780SDimitry Andric   // command line was such that this has no semantic impact on include paths.
3228344a3780SDimitry Andric   for (; It < End &&
3229344a3780SDimitry Andric          Matches(*It, {frontend::System, frontend::ExternCSystem}, false, true);
3230344a3780SDimitry Andric        ++It) {
3231344a3780SDimitry Andric     OptSpecifier Opt = It->Group == frontend::System
3232344a3780SDimitry Andric                            ? OPT_internal_isystem
3233344a3780SDimitry Andric                            : OPT_internal_externc_isystem;
3234b1c73532SDimitry Andric     GenerateArg(Consumer, Opt, It->Path);
3235344a3780SDimitry Andric   }
3236344a3780SDimitry Andric 
3237344a3780SDimitry Andric   assert(It == End && "Unhandled HeaderSearchOption::Entry.");
3238344a3780SDimitry Andric 
3239344a3780SDimitry Andric   // Add the path prefixes which are implicitly treated as being system headers.
3240344a3780SDimitry Andric   for (const auto &P : Opts.SystemHeaderPrefixes) {
3241344a3780SDimitry Andric     OptSpecifier Opt = P.IsSystemHeader ? OPT_system_header_prefix
3242344a3780SDimitry Andric                                         : OPT_no_system_header_prefix;
3243b1c73532SDimitry Andric     GenerateArg(Consumer, Opt, P.Prefix);
3244344a3780SDimitry Andric   }
3245344a3780SDimitry Andric 
3246344a3780SDimitry Andric   for (const std::string &F : Opts.VFSOverlayFiles)
3247b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_ivfsoverlay, F);
3248344a3780SDimitry Andric }
3249344a3780SDimitry Andric 
ParseHeaderSearchArgs(HeaderSearchOptions & Opts,ArgList & Args,DiagnosticsEngine & Diags,const std::string & WorkingDir)3250344a3780SDimitry Andric static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
3251344a3780SDimitry Andric                                   DiagnosticsEngine &Diags,
32527442d6faSDimitry Andric                                   const std::string &WorkingDir) {
3253344a3780SDimitry Andric   unsigned NumErrorsBefore = Diags.getNumErrors();
3254344a3780SDimitry Andric 
3255344a3780SDimitry Andric   HeaderSearchOptions *HeaderSearchOpts = &Opts;
3256344a3780SDimitry Andric 
32577fa27ce4SDimitry Andric #define HEADER_SEARCH_OPTION_WITH_MARSHALLING(...)                             \
32587fa27ce4SDimitry Andric   PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
3259344a3780SDimitry Andric #include "clang/Driver/Options.inc"
3260344a3780SDimitry Andric #undef HEADER_SEARCH_OPTION_WITH_MARSHALLING
3261344a3780SDimitry Andric 
3262180abc3dSDimitry Andric   if (const Arg *A = Args.getLastArg(OPT_stdlib_EQ))
326313cc256eSDimitry Andric     Opts.UseLibcxx = (strcmp(A->getValue(), "libc++") == 0);
32647442d6faSDimitry Andric 
32657442d6faSDimitry Andric   // Canonicalize -fmodules-cache-path before storing it.
32667442d6faSDimitry Andric   SmallString<128> P(Args.getLastArgValue(OPT_fmodules_cache_path));
32677442d6faSDimitry Andric   if (!(P.empty() || llvm::sys::path::is_absolute(P))) {
32687442d6faSDimitry Andric     if (WorkingDir.empty())
32697442d6faSDimitry Andric       llvm::sys::fs::make_absolute(P);
32707442d6faSDimitry Andric     else
32717442d6faSDimitry Andric       llvm::sys::fs::make_absolute(WorkingDir, P);
32727442d6faSDimitry Andric   }
32737442d6faSDimitry Andric   llvm::sys::path::remove_dots(P);
32744df029ccSDimitry Andric   Opts.ModuleCachePath = std::string(P);
32757442d6faSDimitry Andric 
3276461a67faSDimitry Andric   // Only the -fmodule-file=<name>=<file> form.
327748675466SDimitry Andric   for (const auto *A : Args.filtered(OPT_fmodule_file)) {
3278461a67faSDimitry Andric     StringRef Val = A->getValue();
3279c0981da4SDimitry Andric     if (Val.contains('=')) {
3280cfca06d7SDimitry Andric       auto Split = Val.split('=');
3281b1c73532SDimitry Andric       Opts.PrebuiltModuleFiles.insert_or_assign(
3282b1c73532SDimitry Andric           std::string(Split.first), std::string(Split.second));
3283cfca06d7SDimitry Andric     }
3284461a67faSDimitry Andric   }
328548675466SDimitry Andric   for (const auto *A : Args.filtered(OPT_fprebuilt_module_path))
3286bab175ecSDimitry Andric     Opts.AddPrebuiltModulePath(A->getValue());
32879f4dbff6SDimitry Andric 
328848675466SDimitry Andric   for (const auto *A : Args.filtered(OPT_fmodules_ignore_macro)) {
3289798321d8SDimitry Andric     StringRef MacroDef = A->getValue();
3290bab175ecSDimitry Andric     Opts.ModulesIgnoreMacros.insert(
3291bab175ecSDimitry Andric         llvm::CachedHashString(MacroDef.split('=').first));
3292809500fcSDimitry Andric   }
32931569ce68SRoman Divacky 
329436981b17SDimitry Andric   // Add -I..., -F..., and -index-header-map options in order.
329536981b17SDimitry Andric   bool IsIndexHeaderMap = false;
32962b6b257fSDimitry Andric   bool IsSysrootSpecified =
32972b6b257fSDimitry Andric       Args.hasArg(OPT__sysroot_EQ) || Args.hasArg(OPT_isysroot);
3298ac9a064cSDimitry Andric 
3299ac9a064cSDimitry Andric   // Expand a leading `=` to the sysroot if one was passed (and it's not a
3300ac9a064cSDimitry Andric   // framework flag).
3301ac9a064cSDimitry Andric   auto PrefixHeaderPath = [IsSysrootSpecified,
3302ac9a064cSDimitry Andric                            &Opts](const llvm::opt::Arg *A,
3303ac9a064cSDimitry Andric                                   bool IsFramework = false) -> std::string {
3304ac9a064cSDimitry Andric     assert(A->getNumValues() && "Unexpected empty search path flag!");
3305ac9a064cSDimitry Andric     if (IsSysrootSpecified && !IsFramework && A->getValue()[0] == '=') {
3306ac9a064cSDimitry Andric       SmallString<32> Buffer;
3307ac9a064cSDimitry Andric       llvm::sys::path::append(Buffer, Opts.Sysroot,
3308ac9a064cSDimitry Andric                               llvm::StringRef(A->getValue()).substr(1));
3309ac9a064cSDimitry Andric       return std::string(Buffer);
3310ac9a064cSDimitry Andric     }
3311ac9a064cSDimitry Andric     return A->getValue();
3312ac9a064cSDimitry Andric   };
3313ac9a064cSDimitry Andric 
331448675466SDimitry Andric   for (const auto *A : Args.filtered(OPT_I, OPT_F, OPT_index_header_map)) {
3315798321d8SDimitry Andric     if (A->getOption().matches(OPT_index_header_map)) {
331636981b17SDimitry Andric       // -index-header-map applies to the next -I or -F.
331736981b17SDimitry Andric       IsIndexHeaderMap = true;
331836981b17SDimitry Andric       continue;
331936981b17SDimitry Andric     }
332036981b17SDimitry Andric 
3321798321d8SDimitry Andric     frontend::IncludeDirGroup Group =
3322798321d8SDimitry Andric         IsIndexHeaderMap ? frontend::IndexHeaderMap : frontend::Angled;
332336981b17SDimitry Andric 
33242b6b257fSDimitry Andric     bool IsFramework = A->getOption().matches(OPT_F);
3325ac9a064cSDimitry Andric     Opts.AddPath(PrefixHeaderPath(A, IsFramework), Group, IsFramework,
33262b6b257fSDimitry Andric                  /*IgnoreSysroot*/ true);
332736981b17SDimitry Andric     IsIndexHeaderMap = false;
332836981b17SDimitry Andric   }
33291569ce68SRoman Divacky 
3330809500fcSDimitry Andric   // Add -iprefix/-iwithprefix/-iwithprefixbefore options.
333136981b17SDimitry Andric   StringRef Prefix = ""; // FIXME: This isn't the correct default prefix.
333248675466SDimitry Andric   for (const auto *A :
3333798321d8SDimitry Andric        Args.filtered(OPT_iprefix, OPT_iwithprefix, OPT_iwithprefixbefore)) {
33344ba67500SRoman Divacky     if (A->getOption().matches(OPT_iprefix))
333513cc256eSDimitry Andric       Prefix = A->getValue();
33364ba67500SRoman Divacky     else if (A->getOption().matches(OPT_iwithprefix))
3337798321d8SDimitry Andric       Opts.AddPath(Prefix.str() + A->getValue(), frontend::After, false, true);
33381569ce68SRoman Divacky     else
3339798321d8SDimitry Andric       Opts.AddPath(Prefix.str() + A->getValue(), frontend::Angled, false, true);
33401569ce68SRoman Divacky   }
33411569ce68SRoman Divacky 
334248675466SDimitry Andric   for (const auto *A : Args.filtered(OPT_idirafter))
3343ac9a064cSDimitry Andric     Opts.AddPath(PrefixHeaderPath(A), frontend::After, false, true);
334448675466SDimitry Andric   for (const auto *A : Args.filtered(OPT_iquote))
3345ac9a064cSDimitry Andric     Opts.AddPath(PrefixHeaderPath(A), frontend::Quoted, false, true);
3346ac9a064cSDimitry Andric 
3347ac9a064cSDimitry Andric   for (const auto *A : Args.filtered(OPT_isystem, OPT_iwithsysroot)) {
3348ac9a064cSDimitry Andric     if (A->getOption().matches(OPT_iwithsysroot)) {
3349798321d8SDimitry Andric       Opts.AddPath(A->getValue(), frontend::System, false,
3350ac9a064cSDimitry Andric                    /*IgnoreSysRoot=*/false);
3351ac9a064cSDimitry Andric       continue;
3352ac9a064cSDimitry Andric     }
3353ac9a064cSDimitry Andric     Opts.AddPath(PrefixHeaderPath(A), frontend::System, false, true);
3354ac9a064cSDimitry Andric   }
335548675466SDimitry Andric   for (const auto *A : Args.filtered(OPT_iframework))
3356798321d8SDimitry Andric     Opts.AddPath(A->getValue(), frontend::System, true, true);
335748675466SDimitry Andric   for (const auto *A : Args.filtered(OPT_iframeworkwithsysroot))
33587442d6faSDimitry Andric     Opts.AddPath(A->getValue(), frontend::System, /*IsFramework=*/true,
33597442d6faSDimitry Andric                  /*IgnoreSysRoot=*/false);
33601569ce68SRoman Divacky 
336136981b17SDimitry Andric   // Add the paths for the various language specific isystem flags.
336248675466SDimitry Andric   for (const auto *A : Args.filtered(OPT_c_isystem))
3363798321d8SDimitry Andric     Opts.AddPath(A->getValue(), frontend::CSystem, false, true);
336448675466SDimitry Andric   for (const auto *A : Args.filtered(OPT_cxx_isystem))
3365798321d8SDimitry Andric     Opts.AddPath(A->getValue(), frontend::CXXSystem, false, true);
336648675466SDimitry Andric   for (const auto *A : Args.filtered(OPT_objc_isystem))
3367798321d8SDimitry Andric     Opts.AddPath(A->getValue(), frontend::ObjCSystem, false,true);
336848675466SDimitry Andric   for (const auto *A : Args.filtered(OPT_objcxx_isystem))
3369798321d8SDimitry Andric     Opts.AddPath(A->getValue(), frontend::ObjCXXSystem, false, true);
33709da62893SDimitry Andric 
33719da62893SDimitry Andric   // Add the internal paths from a driver that detects standard include paths.
337248675466SDimitry Andric   for (const auto *A :
3373798321d8SDimitry Andric        Args.filtered(OPT_internal_isystem, OPT_internal_externc_isystem)) {
3374809500fcSDimitry Andric     frontend::IncludeDirGroup Group = frontend::System;
3375798321d8SDimitry Andric     if (A->getOption().matches(OPT_internal_externc_isystem))
3376809500fcSDimitry Andric       Group = frontend::ExternCSystem;
3377798321d8SDimitry Andric     Opts.AddPath(A->getValue(), Group, false, true);
3378809500fcSDimitry Andric   }
337956d91b49SDimitry Andric 
338056d91b49SDimitry Andric   // Add the path prefixes which are implicitly treated as being system headers.
338148675466SDimitry Andric   for (const auto *A :
3382798321d8SDimitry Andric        Args.filtered(OPT_system_header_prefix, OPT_no_system_header_prefix))
33839f4dbff6SDimitry Andric     Opts.AddSystemHeaderPrefix(
3384798321d8SDimitry Andric         A->getValue(), A->getOption().matches(OPT_system_header_prefix));
33859f4dbff6SDimitry Andric 
33867fa27ce4SDimitry Andric   for (const auto *A : Args.filtered(OPT_ivfsoverlay, OPT_vfsoverlay))
3387798321d8SDimitry Andric     Opts.AddVFSOverlayFile(A->getValue());
3388344a3780SDimitry Andric 
3389344a3780SDimitry Andric   return Diags.getNumErrors() == NumErrorsBefore;
33901569ce68SRoman Divacky }
33911569ce68SRoman Divacky 
GenerateAPINotesArgs(const APINotesOptions & Opts,ArgumentConsumer Consumer)3392b1c73532SDimitry Andric static void GenerateAPINotesArgs(const APINotesOptions &Opts,
3393b1c73532SDimitry Andric                                  ArgumentConsumer Consumer) {
3394b1c73532SDimitry Andric   if (!Opts.SwiftVersion.empty())
3395b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fapinotes_swift_version,
3396b1c73532SDimitry Andric                 Opts.SwiftVersion.getAsString());
3397b1c73532SDimitry Andric 
3398b1c73532SDimitry Andric   for (const auto &Path : Opts.ModuleSearchPaths)
3399b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_iapinotes_modules, Path);
3400b1c73532SDimitry Andric }
3401b1c73532SDimitry Andric 
ParseAPINotesArgs(APINotesOptions & Opts,ArgList & Args,DiagnosticsEngine & diags)3402b1c73532SDimitry Andric static void ParseAPINotesArgs(APINotesOptions &Opts, ArgList &Args,
3403b1c73532SDimitry Andric                               DiagnosticsEngine &diags) {
3404b1c73532SDimitry Andric   if (const Arg *A = Args.getLastArg(OPT_fapinotes_swift_version)) {
3405b1c73532SDimitry Andric     if (Opts.SwiftVersion.tryParse(A->getValue()))
3406b1c73532SDimitry Andric       diags.Report(diag::err_drv_invalid_value)
3407b1c73532SDimitry Andric           << A->getAsString(Args) << A->getValue();
3408b1c73532SDimitry Andric   }
3409b1c73532SDimitry Andric   for (const Arg *A : Args.filtered(OPT_iapinotes_modules))
3410b1c73532SDimitry Andric     Opts.ModuleSearchPaths.push_back(A->getValue());
3411b1c73532SDimitry Andric }
3412b1c73532SDimitry Andric 
GeneratePointerAuthArgs(const LangOptions & Opts,ArgumentConsumer Consumer)3413ac9a064cSDimitry Andric static void GeneratePointerAuthArgs(const LangOptions &Opts,
3414ac9a064cSDimitry Andric                                     ArgumentConsumer Consumer) {
3415ac9a064cSDimitry Andric   if (Opts.PointerAuthIntrinsics)
3416ac9a064cSDimitry Andric     GenerateArg(Consumer, OPT_fptrauth_intrinsics);
3417ac9a064cSDimitry Andric   if (Opts.PointerAuthCalls)
3418ac9a064cSDimitry Andric     GenerateArg(Consumer, OPT_fptrauth_calls);
3419ac9a064cSDimitry Andric   if (Opts.PointerAuthReturns)
3420ac9a064cSDimitry Andric     GenerateArg(Consumer, OPT_fptrauth_returns);
3421ac9a064cSDimitry Andric   if (Opts.PointerAuthIndirectGotos)
3422ac9a064cSDimitry Andric     GenerateArg(Consumer, OPT_fptrauth_indirect_gotos);
3423ac9a064cSDimitry Andric   if (Opts.PointerAuthAuthTraps)
3424ac9a064cSDimitry Andric     GenerateArg(Consumer, OPT_fptrauth_auth_traps);
3425ac9a064cSDimitry Andric   if (Opts.PointerAuthVTPtrAddressDiscrimination)
3426ac9a064cSDimitry Andric     GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_address_discrimination);
3427ac9a064cSDimitry Andric   if (Opts.PointerAuthVTPtrTypeDiscrimination)
3428ac9a064cSDimitry Andric     GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_type_discrimination);
3429ac9a064cSDimitry Andric   if (Opts.PointerAuthTypeInfoVTPtrDiscrimination)
3430ac9a064cSDimitry Andric     GenerateArg(Consumer, OPT_fptrauth_type_info_vtable_pointer_discrimination);
3431ac9a064cSDimitry Andric 
3432ac9a064cSDimitry Andric   if (Opts.PointerAuthInitFini)
3433ac9a064cSDimitry Andric     GenerateArg(Consumer, OPT_fptrauth_init_fini);
3434ac9a064cSDimitry Andric   if (Opts.PointerAuthFunctionTypeDiscrimination)
3435ac9a064cSDimitry Andric     GenerateArg(Consumer, OPT_fptrauth_function_pointer_type_discrimination);
3436ac9a064cSDimitry Andric }
3437ac9a064cSDimitry Andric 
ParsePointerAuthArgs(LangOptions & Opts,ArgList & Args,DiagnosticsEngine & Diags)3438ac9a064cSDimitry Andric static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,
3439ac9a064cSDimitry Andric                                  DiagnosticsEngine &Diags) {
3440ac9a064cSDimitry Andric   Opts.PointerAuthIntrinsics = Args.hasArg(OPT_fptrauth_intrinsics);
3441ac9a064cSDimitry Andric   Opts.PointerAuthCalls = Args.hasArg(OPT_fptrauth_calls);
3442ac9a064cSDimitry Andric   Opts.PointerAuthReturns = Args.hasArg(OPT_fptrauth_returns);
3443ac9a064cSDimitry Andric   Opts.PointerAuthIndirectGotos = Args.hasArg(OPT_fptrauth_indirect_gotos);
3444ac9a064cSDimitry Andric   Opts.PointerAuthAuthTraps = Args.hasArg(OPT_fptrauth_auth_traps);
3445ac9a064cSDimitry Andric   Opts.PointerAuthVTPtrAddressDiscrimination =
3446ac9a064cSDimitry Andric       Args.hasArg(OPT_fptrauth_vtable_pointer_address_discrimination);
3447ac9a064cSDimitry Andric   Opts.PointerAuthVTPtrTypeDiscrimination =
3448ac9a064cSDimitry Andric       Args.hasArg(OPT_fptrauth_vtable_pointer_type_discrimination);
3449ac9a064cSDimitry Andric   Opts.PointerAuthTypeInfoVTPtrDiscrimination =
3450ac9a064cSDimitry Andric       Args.hasArg(OPT_fptrauth_type_info_vtable_pointer_discrimination);
3451ac9a064cSDimitry Andric 
3452ac9a064cSDimitry Andric   Opts.PointerAuthInitFini = Args.hasArg(OPT_fptrauth_init_fini);
3453ac9a064cSDimitry Andric   Opts.PointerAuthFunctionTypeDiscrimination =
3454ac9a064cSDimitry Andric       Args.hasArg(OPT_fptrauth_function_pointer_type_discrimination);
3455ac9a064cSDimitry Andric }
3456ac9a064cSDimitry Andric 
34577442d6faSDimitry Andric /// Check if input file kind and language standard are compatible.
IsInputCompatibleWithStandard(InputKind IK,const LangStandard & S)34587442d6faSDimitry Andric static bool IsInputCompatibleWithStandard(InputKind IK,
34597442d6faSDimitry Andric                                           const LangStandard &S) {
346057091882SDimitry Andric   switch (IK.getLanguage()) {
3461519fc96cSDimitry Andric   case Language::Unknown:
3462519fc96cSDimitry Andric   case Language::LLVM_IR:
3463ac9a064cSDimitry Andric   case Language::CIR:
346457091882SDimitry Andric     llvm_unreachable("should not parse language flags for this input");
346557091882SDimitry Andric 
3466519fc96cSDimitry Andric   case Language::C:
3467519fc96cSDimitry Andric   case Language::ObjC:
3468519fc96cSDimitry Andric   case Language::RenderScript:
3469519fc96cSDimitry Andric     return S.getLanguage() == Language::C;
347057091882SDimitry Andric 
3471519fc96cSDimitry Andric   case Language::OpenCL:
3472344a3780SDimitry Andric     return S.getLanguage() == Language::OpenCL ||
3473344a3780SDimitry Andric            S.getLanguage() == Language::OpenCLCXX;
3474344a3780SDimitry Andric 
3475344a3780SDimitry Andric   case Language::OpenCLCXX:
3476344a3780SDimitry Andric     return S.getLanguage() == Language::OpenCLCXX;
347757091882SDimitry Andric 
3478519fc96cSDimitry Andric   case Language::CXX:
3479519fc96cSDimitry Andric   case Language::ObjCXX:
3480519fc96cSDimitry Andric     return S.getLanguage() == Language::CXX;
348157091882SDimitry Andric 
3482519fc96cSDimitry Andric   case Language::CUDA:
348357091882SDimitry Andric     // FIXME: What -std= values should be permitted for CUDA compilations?
3484519fc96cSDimitry Andric     return S.getLanguage() == Language::CUDA ||
3485519fc96cSDimitry Andric            S.getLanguage() == Language::CXX;
348657091882SDimitry Andric 
3487519fc96cSDimitry Andric   case Language::HIP:
3488519fc96cSDimitry Andric     return S.getLanguage() == Language::CXX || S.getLanguage() == Language::HIP;
348948675466SDimitry Andric 
3490519fc96cSDimitry Andric   case Language::Asm:
349157091882SDimitry Andric     // Accept (and ignore) all -std= values.
349257091882SDimitry Andric     // FIXME: The -std= value is not ignored; it affects the tokenization
349357091882SDimitry Andric     // and preprocessing rules if we're preprocessing this asm input.
34947442d6faSDimitry Andric     return true;
3495145449b1SDimitry Andric 
3496145449b1SDimitry Andric   case Language::HLSL:
3497145449b1SDimitry Andric     return S.getLanguage() == Language::HLSL;
34987442d6faSDimitry Andric   }
349957091882SDimitry Andric 
350057091882SDimitry Andric   llvm_unreachable("unexpected input language");
35017442d6faSDimitry Andric }
35027442d6faSDimitry Andric 
35037442d6faSDimitry Andric /// Get language name for given input kind.
GetInputKindName(InputKind IK)35046f8fc217SDimitry Andric static StringRef GetInputKindName(InputKind IK) {
350557091882SDimitry Andric   switch (IK.getLanguage()) {
3506519fc96cSDimitry Andric   case Language::C:
350757091882SDimitry Andric     return "C";
3508519fc96cSDimitry Andric   case Language::ObjC:
350957091882SDimitry Andric     return "Objective-C";
3510519fc96cSDimitry Andric   case Language::CXX:
351157091882SDimitry Andric     return "C++";
3512519fc96cSDimitry Andric   case Language::ObjCXX:
351357091882SDimitry Andric     return "Objective-C++";
3514519fc96cSDimitry Andric   case Language::OpenCL:
35157442d6faSDimitry Andric     return "OpenCL";
3516344a3780SDimitry Andric   case Language::OpenCLCXX:
3517344a3780SDimitry Andric     return "C++ for OpenCL";
3518519fc96cSDimitry Andric   case Language::CUDA:
35197442d6faSDimitry Andric     return "CUDA";
3520519fc96cSDimitry Andric   case Language::RenderScript:
352157091882SDimitry Andric     return "RenderScript";
3522519fc96cSDimitry Andric   case Language::HIP:
352348675466SDimitry Andric     return "HIP";
352457091882SDimitry Andric 
3525519fc96cSDimitry Andric   case Language::Asm:
352657091882SDimitry Andric     return "Asm";
3527519fc96cSDimitry Andric   case Language::LLVM_IR:
352857091882SDimitry Andric     return "LLVM IR";
3529ac9a064cSDimitry Andric   case Language::CIR:
3530ac9a064cSDimitry Andric     return "Clang IR";
353157091882SDimitry Andric 
3532145449b1SDimitry Andric   case Language::HLSL:
3533145449b1SDimitry Andric     return "HLSL";
3534145449b1SDimitry Andric 
3535519fc96cSDimitry Andric   case Language::Unknown:
353657091882SDimitry Andric     break;
35377442d6faSDimitry Andric   }
353857091882SDimitry Andric   llvm_unreachable("unknown input language");
35397442d6faSDimitry Andric }
35407442d6faSDimitry Andric 
GenerateLangArgs(const LangOptions & Opts,ArgumentConsumer Consumer,const llvm::Triple & T,InputKind IK)3541b1c73532SDimitry Andric void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts,
3542b1c73532SDimitry Andric                                               ArgumentConsumer Consumer,
3543b1c73532SDimitry Andric                                               const llvm::Triple &T,
3544b1c73532SDimitry Andric                                               InputKind IK) {
3545344a3780SDimitry Andric   if (IK.getFormat() == InputKind::Precompiled ||
3546ac9a064cSDimitry Andric       IK.getLanguage() == Language::LLVM_IR ||
3547ac9a064cSDimitry Andric       IK.getLanguage() == Language::CIR) {
3548344a3780SDimitry Andric     if (Opts.ObjCAutoRefCount)
3549b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_fobjc_arc);
3550344a3780SDimitry Andric     if (Opts.PICLevel != 0)
3551b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_pic_level, Twine(Opts.PICLevel));
3552344a3780SDimitry Andric     if (Opts.PIE)
3553b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_pic_is_pie);
3554344a3780SDimitry Andric     for (StringRef Sanitizer : serializeSanitizerKinds(Opts.Sanitize))
3555b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_fsanitize_EQ, Sanitizer);
3556344a3780SDimitry Andric 
3557344a3780SDimitry Andric     return;
3558b60736ecSDimitry Andric   }
3559b60736ecSDimitry Andric 
3560344a3780SDimitry Andric   OptSpecifier StdOpt;
3561344a3780SDimitry Andric   switch (Opts.LangStd) {
3562344a3780SDimitry Andric   case LangStandard::lang_opencl10:
3563344a3780SDimitry Andric   case LangStandard::lang_opencl11:
3564344a3780SDimitry Andric   case LangStandard::lang_opencl12:
3565344a3780SDimitry Andric   case LangStandard::lang_opencl20:
3566344a3780SDimitry Andric   case LangStandard::lang_opencl30:
3567c0981da4SDimitry Andric   case LangStandard::lang_openclcpp10:
3568c0981da4SDimitry Andric   case LangStandard::lang_openclcpp2021:
3569344a3780SDimitry Andric     StdOpt = OPT_cl_std_EQ;
3570344a3780SDimitry Andric     break;
3571344a3780SDimitry Andric   default:
3572344a3780SDimitry Andric     StdOpt = OPT_std_EQ;
3573344a3780SDimitry Andric     break;
3574344a3780SDimitry Andric   }
3575344a3780SDimitry Andric 
3576344a3780SDimitry Andric   auto LangStandard = LangStandard::getLangStandardForKind(Opts.LangStd);
3577b1c73532SDimitry Andric   GenerateArg(Consumer, StdOpt, LangStandard.getName());
3578344a3780SDimitry Andric 
3579344a3780SDimitry Andric   if (Opts.IncludeDefaultHeader)
3580b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_finclude_default_header);
3581344a3780SDimitry Andric   if (Opts.DeclareOpenCLBuiltins)
3582b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fdeclare_opencl_builtins);
3583344a3780SDimitry Andric 
3584344a3780SDimitry Andric   const LangOptions *LangOpts = &Opts;
3585344a3780SDimitry Andric 
35867fa27ce4SDimitry Andric #define LANG_OPTION_WITH_MARSHALLING(...)                                      \
3587b1c73532SDimitry Andric   GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
3588344a3780SDimitry Andric #include "clang/Driver/Options.inc"
3589344a3780SDimitry Andric #undef LANG_OPTION_WITH_MARSHALLING
3590344a3780SDimitry Andric 
3591344a3780SDimitry Andric   // The '-fcf-protection=' option is generated by CodeGenOpts generator.
3592344a3780SDimitry Andric 
3593344a3780SDimitry Andric   if (Opts.ObjC) {
3594b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fobjc_runtime_EQ, Opts.ObjCRuntime.getAsString());
3595344a3780SDimitry Andric 
3596344a3780SDimitry Andric     if (Opts.GC == LangOptions::GCOnly)
3597b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_fobjc_gc_only);
3598344a3780SDimitry Andric     else if (Opts.GC == LangOptions::HybridGC)
3599b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_fobjc_gc);
3600344a3780SDimitry Andric     else if (Opts.ObjCAutoRefCount == 1)
3601b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_fobjc_arc);
3602344a3780SDimitry Andric 
3603344a3780SDimitry Andric     if (Opts.ObjCWeakRuntime)
3604b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_fobjc_runtime_has_weak);
3605344a3780SDimitry Andric 
3606344a3780SDimitry Andric     if (Opts.ObjCWeak)
3607b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_fobjc_weak);
3608344a3780SDimitry Andric 
3609344a3780SDimitry Andric     if (Opts.ObjCSubscriptingLegacyRuntime)
3610b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_fobjc_subscripting_legacy_runtime);
3611344a3780SDimitry Andric   }
3612344a3780SDimitry Andric 
3613344a3780SDimitry Andric   if (Opts.GNUCVersion != 0) {
3614344a3780SDimitry Andric     unsigned Major = Opts.GNUCVersion / 100 / 100;
3615344a3780SDimitry Andric     unsigned Minor = (Opts.GNUCVersion / 100) % 100;
3616344a3780SDimitry Andric     unsigned Patch = Opts.GNUCVersion % 100;
3617b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fgnuc_version_EQ,
3618b1c73532SDimitry Andric                 Twine(Major) + "." + Twine(Minor) + "." + Twine(Patch));
3619344a3780SDimitry Andric   }
3620344a3780SDimitry Andric 
3621344a3780SDimitry Andric   if (Opts.IgnoreXCOFFVisibility)
3622b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_mignore_xcoff_visibility);
3623344a3780SDimitry Andric 
3624344a3780SDimitry Andric   if (Opts.SignedOverflowBehavior == LangOptions::SOB_Trapping) {
3625b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_ftrapv);
3626b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_ftrapv_handler, Opts.OverflowHandler);
3627344a3780SDimitry Andric   } else if (Opts.SignedOverflowBehavior == LangOptions::SOB_Defined) {
3628b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fwrapv);
3629344a3780SDimitry Andric   }
3630344a3780SDimitry Andric 
3631344a3780SDimitry Andric   if (Opts.MSCompatibilityVersion != 0) {
3632344a3780SDimitry Andric     unsigned Major = Opts.MSCompatibilityVersion / 10000000;
3633344a3780SDimitry Andric     unsigned Minor = (Opts.MSCompatibilityVersion / 100000) % 100;
3634344a3780SDimitry Andric     unsigned Subminor = Opts.MSCompatibilityVersion % 100000;
3635b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fms_compatibility_version,
3636b1c73532SDimitry Andric                 Twine(Major) + "." + Twine(Minor) + "." + Twine(Subminor));
3637344a3780SDimitry Andric   }
3638344a3780SDimitry Andric 
36394df029ccSDimitry Andric   if ((!Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus17 && !Opts.C23) ||
36404df029ccSDimitry Andric       T.isOSzOS()) {
3641344a3780SDimitry Andric     if (!Opts.Trigraphs)
3642b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_fno_trigraphs);
3643344a3780SDimitry Andric   } else {
3644344a3780SDimitry Andric     if (Opts.Trigraphs)
3645b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_ftrigraphs);
3646344a3780SDimitry Andric   }
3647344a3780SDimitry Andric 
3648344a3780SDimitry Andric   if (Opts.Blocks && !(Opts.OpenCL && Opts.OpenCLVersion == 200))
3649b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fblocks);
3650344a3780SDimitry Andric 
3651344a3780SDimitry Andric   if (Opts.ConvergentFunctions &&
3652ac9a064cSDimitry Andric       !(Opts.OpenCL || (Opts.CUDA && Opts.CUDAIsDevice) || Opts.SYCLIsDevice ||
3653ac9a064cSDimitry Andric         Opts.HLSL))
3654b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fconvergent_functions);
3655344a3780SDimitry Andric 
3656344a3780SDimitry Andric   if (Opts.NoBuiltin && !Opts.Freestanding)
3657b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fno_builtin);
3658344a3780SDimitry Andric 
3659344a3780SDimitry Andric   if (!Opts.NoBuiltin)
3660344a3780SDimitry Andric     for (const auto &Func : Opts.NoBuiltinFuncs)
3661b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_fno_builtin_, Func);
3662344a3780SDimitry Andric 
3663344a3780SDimitry Andric   if (Opts.LongDoubleSize == 128)
3664b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_mlong_double_128);
3665344a3780SDimitry Andric   else if (Opts.LongDoubleSize == 64)
3666b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_mlong_double_64);
3667145449b1SDimitry Andric   else if (Opts.LongDoubleSize == 80)
3668b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_mlong_double_80);
3669344a3780SDimitry Andric 
3670344a3780SDimitry Andric   // Not generating '-mrtd', it's just an alias for '-fdefault-calling-conv='.
3671344a3780SDimitry Andric 
3672344a3780SDimitry Andric   // OpenMP was requested via '-fopenmp', not implied by '-fopenmp-simd' or
3673344a3780SDimitry Andric   // '-fopenmp-targets='.
3674344a3780SDimitry Andric   if (Opts.OpenMP && !Opts.OpenMPSimd) {
3675b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fopenmp);
3676344a3780SDimitry Andric 
36777fa27ce4SDimitry Andric     if (Opts.OpenMP != 51)
3678b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_fopenmp_version_EQ, Twine(Opts.OpenMP));
3679344a3780SDimitry Andric 
3680344a3780SDimitry Andric     if (!Opts.OpenMPUseTLS)
3681b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_fnoopenmp_use_tls);
3682344a3780SDimitry Andric 
36837fa27ce4SDimitry Andric     if (Opts.OpenMPIsTargetDevice)
3684b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_fopenmp_is_target_device);
3685344a3780SDimitry Andric 
3686344a3780SDimitry Andric     if (Opts.OpenMPIRBuilder)
3687b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_fopenmp_enable_irbuilder);
3688344a3780SDimitry Andric   }
3689344a3780SDimitry Andric 
3690344a3780SDimitry Andric   if (Opts.OpenMPSimd) {
3691b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fopenmp_simd);
3692344a3780SDimitry Andric 
36937fa27ce4SDimitry Andric     if (Opts.OpenMP != 51)
3694b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_fopenmp_version_EQ, Twine(Opts.OpenMP));
3695344a3780SDimitry Andric   }
3696344a3780SDimitry Andric 
3697c0981da4SDimitry Andric   if (Opts.OpenMPThreadSubscription)
3698b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fopenmp_assume_threads_oversubscription);
3699c0981da4SDimitry Andric 
3700c0981da4SDimitry Andric   if (Opts.OpenMPTeamSubscription)
3701b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fopenmp_assume_teams_oversubscription);
3702c0981da4SDimitry Andric 
3703c0981da4SDimitry Andric   if (Opts.OpenMPTargetDebug != 0)
3704b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fopenmp_target_debug_EQ,
3705b1c73532SDimitry Andric                 Twine(Opts.OpenMPTargetDebug));
3706c0981da4SDimitry Andric 
3707344a3780SDimitry Andric   if (Opts.OpenMPCUDANumSMs != 0)
3708b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fopenmp_cuda_number_of_sm_EQ,
3709b1c73532SDimitry Andric                 Twine(Opts.OpenMPCUDANumSMs));
3710344a3780SDimitry Andric 
3711344a3780SDimitry Andric   if (Opts.OpenMPCUDABlocksPerSM != 0)
3712b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fopenmp_cuda_blocks_per_sm_EQ,
3713b1c73532SDimitry Andric                 Twine(Opts.OpenMPCUDABlocksPerSM));
3714344a3780SDimitry Andric 
3715344a3780SDimitry Andric   if (Opts.OpenMPCUDAReductionBufNum != 1024)
3716b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fopenmp_cuda_teams_reduction_recs_num_EQ,
3717b1c73532SDimitry Andric                 Twine(Opts.OpenMPCUDAReductionBufNum));
3718344a3780SDimitry Andric 
3719344a3780SDimitry Andric   if (!Opts.OMPTargetTriples.empty()) {
3720344a3780SDimitry Andric     std::string Targets;
3721344a3780SDimitry Andric     llvm::raw_string_ostream OS(Targets);
3722344a3780SDimitry Andric     llvm::interleave(
3723344a3780SDimitry Andric         Opts.OMPTargetTriples, OS,
3724344a3780SDimitry Andric         [&OS](const llvm::Triple &T) { OS << T.str(); }, ",");
3725b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fopenmp_targets_EQ, OS.str());
3726344a3780SDimitry Andric   }
3727344a3780SDimitry Andric 
3728344a3780SDimitry Andric   if (!Opts.OMPHostIRFile.empty())
3729b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fopenmp_host_ir_file_path, Opts.OMPHostIRFile);
3730344a3780SDimitry Andric 
3731344a3780SDimitry Andric   if (Opts.OpenMPCUDAMode)
3732b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fopenmp_cuda_mode);
3733b1c73532SDimitry Andric 
3734b1c73532SDimitry Andric   if (Opts.OpenACC) {
3735b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fopenacc);
3736b1c73532SDimitry Andric     if (!Opts.OpenACCMacroOverride.empty())
3737b1c73532SDimitry Andric       GenerateArg(Consumer, OPT_openacc_macro_override,
3738b1c73532SDimitry Andric                   Opts.OpenACCMacroOverride);
3739b1c73532SDimitry Andric   }
3740344a3780SDimitry Andric 
3741344a3780SDimitry Andric   // The arguments used to set Optimize, OptimizeSize and NoInlineDefine are
3742344a3780SDimitry Andric   // generated from CodeGenOptions.
3743344a3780SDimitry Andric 
3744344a3780SDimitry Andric   if (Opts.DefaultFPContractMode == LangOptions::FPM_Fast)
3745b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_ffp_contract, "fast");
3746344a3780SDimitry Andric   else if (Opts.DefaultFPContractMode == LangOptions::FPM_On)
3747b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_ffp_contract, "on");
3748344a3780SDimitry Andric   else if (Opts.DefaultFPContractMode == LangOptions::FPM_Off)
3749b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_ffp_contract, "off");
3750344a3780SDimitry Andric   else if (Opts.DefaultFPContractMode == LangOptions::FPM_FastHonorPragmas)
3751b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_ffp_contract, "fast-honor-pragmas");
3752344a3780SDimitry Andric 
3753344a3780SDimitry Andric   for (StringRef Sanitizer : serializeSanitizerKinds(Opts.Sanitize))
3754b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fsanitize_EQ, Sanitizer);
3755344a3780SDimitry Andric 
3756344a3780SDimitry Andric   // Conflating '-fsanitize-system-ignorelist' and '-fsanitize-ignorelist'.
3757344a3780SDimitry Andric   for (const std::string &F : Opts.NoSanitizeFiles)
3758b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fsanitize_ignorelist_EQ, F);
3759344a3780SDimitry Andric 
3760b1c73532SDimitry Andric   switch (Opts.getClangABICompat()) {
3761b1c73532SDimitry Andric   case LangOptions::ClangABI::Ver3_8:
3762b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "3.8");
3763b1c73532SDimitry Andric     break;
3764b1c73532SDimitry Andric   case LangOptions::ClangABI::Ver4:
3765b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "4.0");
3766b1c73532SDimitry Andric     break;
3767b1c73532SDimitry Andric   case LangOptions::ClangABI::Ver6:
3768b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "6.0");
3769b1c73532SDimitry Andric     break;
3770b1c73532SDimitry Andric   case LangOptions::ClangABI::Ver7:
3771b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "7.0");
3772b1c73532SDimitry Andric     break;
3773b1c73532SDimitry Andric   case LangOptions::ClangABI::Ver9:
3774b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "9.0");
3775b1c73532SDimitry Andric     break;
3776b1c73532SDimitry Andric   case LangOptions::ClangABI::Ver11:
3777b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "11.0");
3778b1c73532SDimitry Andric     break;
3779b1c73532SDimitry Andric   case LangOptions::ClangABI::Ver12:
3780b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "12.0");
3781b1c73532SDimitry Andric     break;
3782b1c73532SDimitry Andric   case LangOptions::ClangABI::Ver14:
3783b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "14.0");
3784b1c73532SDimitry Andric     break;
3785b1c73532SDimitry Andric   case LangOptions::ClangABI::Ver15:
3786b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "15.0");
3787b1c73532SDimitry Andric     break;
3788b1c73532SDimitry Andric   case LangOptions::ClangABI::Ver17:
3789b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "17.0");
3790b1c73532SDimitry Andric     break;
3791ac9a064cSDimitry Andric   case LangOptions::ClangABI::Ver18:
3792ac9a064cSDimitry Andric     GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "18.0");
3793ac9a064cSDimitry Andric     break;
3794b1c73532SDimitry Andric   case LangOptions::ClangABI::Latest:
3795b1c73532SDimitry Andric     break;
3796b1c73532SDimitry Andric   }
3797344a3780SDimitry Andric 
3798344a3780SDimitry Andric   if (Opts.getSignReturnAddressScope() ==
3799344a3780SDimitry Andric       LangOptions::SignReturnAddressScopeKind::All)
3800b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_msign_return_address_EQ, "all");
3801344a3780SDimitry Andric   else if (Opts.getSignReturnAddressScope() ==
3802344a3780SDimitry Andric            LangOptions::SignReturnAddressScopeKind::NonLeaf)
3803b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_msign_return_address_EQ, "non-leaf");
3804344a3780SDimitry Andric 
3805344a3780SDimitry Andric   if (Opts.getSignReturnAddressKey() ==
3806344a3780SDimitry Andric       LangOptions::SignReturnAddressKeyKind::BKey)
3807b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_msign_return_address_key_EQ, "b_key");
3808344a3780SDimitry Andric 
3809344a3780SDimitry Andric   if (Opts.CXXABI)
3810b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fcxx_abi_EQ,
3811b1c73532SDimitry Andric                 TargetCXXABI::getSpelling(*Opts.CXXABI));
3812344a3780SDimitry Andric 
3813344a3780SDimitry Andric   if (Opts.RelativeCXXABIVTables)
3814b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fexperimental_relative_cxx_abi_vtables);
3815344a3780SDimitry Andric   else
3816b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fno_experimental_relative_cxx_abi_vtables);
3817c0981da4SDimitry Andric 
3818145449b1SDimitry Andric   if (Opts.UseTargetPathSeparator)
3819b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_ffile_reproducible);
3820145449b1SDimitry Andric   else
3821b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fno_file_reproducible);
3822145449b1SDimitry Andric 
3823c0981da4SDimitry Andric   for (const auto &MP : Opts.MacroPrefixMap)
3824b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fmacro_prefix_map_EQ, MP.first + "=" + MP.second);
3825145449b1SDimitry Andric 
3826145449b1SDimitry Andric   if (!Opts.RandstructSeed.empty())
3827b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_frandomize_layout_seed_EQ, Opts.RandstructSeed);
3828344a3780SDimitry Andric }
3829344a3780SDimitry Andric 
ParseLangArgs(LangOptions & Opts,ArgList & Args,InputKind IK,const llvm::Triple & T,std::vector<std::string> & Includes,DiagnosticsEngine & Diags)3830344a3780SDimitry Andric bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
3831b60736ecSDimitry Andric                                        InputKind IK, const llvm::Triple &T,
3832b60736ecSDimitry Andric                                        std::vector<std::string> &Includes,
383336981b17SDimitry Andric                                        DiagnosticsEngine &Diags) {
3834344a3780SDimitry Andric   unsigned NumErrorsBefore = Diags.getNumErrors();
3835344a3780SDimitry Andric 
3836344a3780SDimitry Andric   if (IK.getFormat() == InputKind::Precompiled ||
3837ac9a064cSDimitry Andric       IK.getLanguage() == Language::LLVM_IR ||
3838ac9a064cSDimitry Andric       IK.getLanguage() == Language::CIR) {
3839344a3780SDimitry Andric     // ObjCAAutoRefCount and Sanitize LangOpts are used to setup the
3840344a3780SDimitry Andric     // PassManager in BackendUtil.cpp. They need to be initialized no matter
3841344a3780SDimitry Andric     // what the input type is.
3842344a3780SDimitry Andric     if (Args.hasArg(OPT_fobjc_arc))
3843344a3780SDimitry Andric       Opts.ObjCAutoRefCount = 1;
3844344a3780SDimitry Andric     // PICLevel and PIELevel are needed during code generation and this should
3845344a3780SDimitry Andric     // be set regardless of the input type.
3846344a3780SDimitry Andric     Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags);
3847344a3780SDimitry Andric     Opts.PIE = Args.hasArg(OPT_pic_is_pie);
3848344a3780SDimitry Andric     parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ),
3849344a3780SDimitry Andric                         Diags, Opts.Sanitize);
3850344a3780SDimitry Andric 
3851344a3780SDimitry Andric     return Diags.getNumErrors() == NumErrorsBefore;
3852344a3780SDimitry Andric   }
3853344a3780SDimitry Andric 
3854344a3780SDimitry Andric   // Other LangOpts are only initialized when the input is not AST or LLVM IR.
3855344a3780SDimitry Andric   // FIXME: Should we really be parsing this for an Language::Asm input?
3856344a3780SDimitry Andric 
3857bca07a45SDimitry Andric   // FIXME: Cleanup per-file based stuff.
3858bca07a45SDimitry Andric   LangStandard::Kind LangStd = LangStandard::lang_unspecified;
3859bca07a45SDimitry Andric   if (const Arg *A = Args.getLastArg(OPT_std_EQ)) {
3860519fc96cSDimitry Andric     LangStd = LangStandard::getLangKind(A->getValue());
38617442d6faSDimitry Andric     if (LangStd == LangStandard::lang_unspecified) {
3862bca07a45SDimitry Andric       Diags.Report(diag::err_drv_invalid_value)
386313cc256eSDimitry Andric         << A->getAsString(Args) << A->getValue();
38647442d6faSDimitry Andric       // Report supported standards with short description.
38657442d6faSDimitry Andric       for (unsigned KindValue = 0;
38667442d6faSDimitry Andric            KindValue != LangStandard::lang_unspecified;
38677442d6faSDimitry Andric            ++KindValue) {
38687442d6faSDimitry Andric         const LangStandard &Std = LangStandard::getLangStandardForKind(
38697442d6faSDimitry Andric           static_cast<LangStandard::Kind>(KindValue));
38707442d6faSDimitry Andric         if (IsInputCompatibleWithStandard(IK, Std)) {
387157091882SDimitry Andric           auto Diag = Diags.Report(diag::note_drv_use_standard);
387257091882SDimitry Andric           Diag << Std.getName() << Std.getDescription();
387357091882SDimitry Andric           unsigned NumAliases = 0;
387457091882SDimitry Andric #define LANGSTANDARD(id, name, lang, desc, features)
387557091882SDimitry Andric #define LANGSTANDARD_ALIAS(id, alias) \
387657091882SDimitry Andric           if (KindValue == LangStandard::lang_##id) ++NumAliases;
387757091882SDimitry Andric #define LANGSTANDARD_ALIAS_DEPR(id, alias)
3878519fc96cSDimitry Andric #include "clang/Basic/LangStandards.def"
387957091882SDimitry Andric           Diag << NumAliases;
388057091882SDimitry Andric #define LANGSTANDARD(id, name, lang, desc, features)
388157091882SDimitry Andric #define LANGSTANDARD_ALIAS(id, alias) \
388257091882SDimitry Andric           if (KindValue == LangStandard::lang_##id) Diag << alias;
388357091882SDimitry Andric #define LANGSTANDARD_ALIAS_DEPR(id, alias)
3884519fc96cSDimitry Andric #include "clang/Basic/LangStandards.def"
38857442d6faSDimitry Andric         }
38867442d6faSDimitry Andric       }
38877442d6faSDimitry Andric     } else {
38889f4dbff6SDimitry Andric       // Valid standard, check to make sure language and standard are
38899f4dbff6SDimitry Andric       // compatible.
389029cafa66SDimitry Andric       const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd);
38917442d6faSDimitry Andric       if (!IsInputCompatibleWithStandard(IK, Std)) {
389229cafa66SDimitry Andric         Diags.Report(diag::err_drv_argument_not_allowed_with)
38937442d6faSDimitry Andric           << A->getAsString(Args) << GetInputKindName(IK);
389429cafa66SDimitry Andric       }
389529cafa66SDimitry Andric     }
3896bca07a45SDimitry Andric   }
3897bca07a45SDimitry Andric 
389856d91b49SDimitry Andric   // -cl-std only applies for OpenCL language standards.
389956d91b49SDimitry Andric   // Override the -std option in this case.
3900bca07a45SDimitry Andric   if (const Arg *A = Args.getLastArg(OPT_cl_std_EQ)) {
390156d91b49SDimitry Andric     LangStandard::Kind OpenCLLangStd
390213cc256eSDimitry Andric       = llvm::StringSwitch<LangStandard::Kind>(A->getValue())
390357091882SDimitry Andric         .Cases("cl", "CL", LangStandard::lang_opencl10)
3904b60736ecSDimitry Andric         .Cases("cl1.0", "CL1.0", LangStandard::lang_opencl10)
39052b6b257fSDimitry Andric         .Cases("cl1.1", "CL1.1", LangStandard::lang_opencl11)
39062b6b257fSDimitry Andric         .Cases("cl1.2", "CL1.2", LangStandard::lang_opencl12)
39072b6b257fSDimitry Andric         .Cases("cl2.0", "CL2.0", LangStandard::lang_opencl20)
3908b60736ecSDimitry Andric         .Cases("cl3.0", "CL3.0", LangStandard::lang_opencl30)
3909c0981da4SDimitry Andric         .Cases("clc++", "CLC++", LangStandard::lang_openclcpp10)
3910c0981da4SDimitry Andric         .Cases("clc++1.0", "CLC++1.0", LangStandard::lang_openclcpp10)
3911c0981da4SDimitry Andric         .Cases("clc++2021", "CLC++2021", LangStandard::lang_openclcpp2021)
391256d91b49SDimitry Andric         .Default(LangStandard::lang_unspecified);
391356d91b49SDimitry Andric 
391456d91b49SDimitry Andric     if (OpenCLLangStd == LangStandard::lang_unspecified) {
3915bca07a45SDimitry Andric       Diags.Report(diag::err_drv_invalid_value)
391613cc256eSDimitry Andric         << A->getAsString(Args) << A->getValue();
3917bca07a45SDimitry Andric     }
391856d91b49SDimitry Andric     else
391956d91b49SDimitry Andric       LangStd = OpenCLLangStd;
3920bca07a45SDimitry Andric   }
3921bca07a45SDimitry Andric 
3922b60736ecSDimitry Andric   // These need to be parsed now. They are used to set OpenCL defaults.
39232b6b257fSDimitry Andric   Opts.IncludeDefaultHeader = Args.hasArg(OPT_finclude_default_header);
392422989816SDimitry Andric   Opts.DeclareOpenCLBuiltins = Args.hasArg(OPT_fdeclare_opencl_builtins);
39252b6b257fSDimitry Andric 
3926145449b1SDimitry Andric   LangOptions::setLangDefaults(Opts, IK.getLanguage(), T, Includes, LangStd);
39272b6b257fSDimitry Andric 
3928b60736ecSDimitry Andric   // The key paths of codegen options defined in Options.td start with
3929b60736ecSDimitry Andric   // "LangOpts->". Let's provide the expected variable name and type.
3930b60736ecSDimitry Andric   LangOptions *LangOpts = &Opts;
3931b60736ecSDimitry Andric 
39327fa27ce4SDimitry Andric #define LANG_OPTION_WITH_MARSHALLING(...)                                      \
39337fa27ce4SDimitry Andric   PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
3934b60736ecSDimitry Andric #include "clang/Driver/Options.inc"
3935b60736ecSDimitry Andric #undef LANG_OPTION_WITH_MARSHALLING
3936b60736ecSDimitry Andric 
3937b60736ecSDimitry Andric   if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) {
3938b60736ecSDimitry Andric     StringRef Name = A->getValue();
3939b60736ecSDimitry Andric     if (Name == "full" || Name == "branch") {
3940b60736ecSDimitry Andric       Opts.CFProtectionBranch = 1;
39412b6b257fSDimitry Andric     }
3942b60736ecSDimitry Andric   }
394348675466SDimitry Andric 
3944344a3780SDimitry Andric   if ((Args.hasArg(OPT_fsycl_is_device) || Args.hasArg(OPT_fsycl_is_host)) &&
3945344a3780SDimitry Andric       !Args.hasArg(OPT_sycl_std_EQ)) {
3946344a3780SDimitry Andric     // If the user supplied -fsycl-is-device or -fsycl-is-host, but failed to
3947344a3780SDimitry Andric     // provide -sycl-std=, we want to default it to whatever the default SYCL
3948344a3780SDimitry Andric     // version is. I could not find a way to express this with the options
3949344a3780SDimitry Andric     // tablegen because we still want this value to be SYCL_None when the user
3950344a3780SDimitry Andric     // is not in device or host mode.
3951344a3780SDimitry Andric     Opts.setSYCLVersion(LangOptions::SYCL_Default);
3952344a3780SDimitry Andric   }
39531569ce68SRoman Divacky 
3954676fbe81SDimitry Andric   if (Opts.ObjC) {
395556d91b49SDimitry Andric     if (Arg *arg = Args.getLastArg(OPT_fobjc_runtime_EQ)) {
395613cc256eSDimitry Andric       StringRef value = arg->getValue();
395756d91b49SDimitry Andric       if (Opts.ObjCRuntime.tryParse(value))
395856d91b49SDimitry Andric         Diags.Report(diag::err_drv_unknown_objc_runtime) << value;
395956d91b49SDimitry Andric     }
396056d91b49SDimitry Andric 
39611569ce68SRoman Divacky     if (Args.hasArg(OPT_fobjc_gc_only))
396236981b17SDimitry Andric       Opts.setGC(LangOptions::GCOnly);
39631569ce68SRoman Divacky     else if (Args.hasArg(OPT_fobjc_gc))
396436981b17SDimitry Andric       Opts.setGC(LangOptions::HybridGC);
3965180abc3dSDimitry Andric     else if (Args.hasArg(OPT_fobjc_arc)) {
3966180abc3dSDimitry Andric       Opts.ObjCAutoRefCount = 1;
396713cc256eSDimitry Andric       if (!Opts.ObjCRuntime.allowsARC())
396813cc256eSDimitry Andric         Diags.Report(diag::err_arc_unsupported_on_runtime);
396945b53394SDimitry Andric     }
39701569ce68SRoman Divacky 
397145b53394SDimitry Andric     // ObjCWeakRuntime tracks whether the runtime supports __weak, not
397245b53394SDimitry Andric     // whether the feature is actually enabled.  This is predominantly
397345b53394SDimitry Andric     // determined by -fobjc-runtime, but we allow it to be overridden
397445b53394SDimitry Andric     // from the command line for testing purposes.
3975180abc3dSDimitry Andric     if (Args.hasArg(OPT_fobjc_runtime_has_weak))
397645b53394SDimitry Andric       Opts.ObjCWeakRuntime = 1;
397713cc256eSDimitry Andric     else
397845b53394SDimitry Andric       Opts.ObjCWeakRuntime = Opts.ObjCRuntime.allowsWeak();
397945b53394SDimitry Andric 
398045b53394SDimitry Andric     // ObjCWeak determines whether __weak is actually enabled.
398145b53394SDimitry Andric     // Note that we allow -fno-objc-weak to disable this even in ARC mode.
398245b53394SDimitry Andric     if (auto weakArg = Args.getLastArg(OPT_fobjc_weak, OPT_fno_objc_weak)) {
398345b53394SDimitry Andric       if (!weakArg->getOption().matches(OPT_fobjc_weak)) {
398445b53394SDimitry Andric         assert(!Opts.ObjCWeak);
398545b53394SDimitry Andric       } else if (Opts.getGC() != LangOptions::NonGC) {
398645b53394SDimitry Andric         Diags.Report(diag::err_objc_weak_with_gc);
398745b53394SDimitry Andric       } else if (!Opts.ObjCWeakRuntime) {
398845b53394SDimitry Andric         Diags.Report(diag::err_objc_weak_unsupported);
398945b53394SDimitry Andric       } else {
399045b53394SDimitry Andric         Opts.ObjCWeak = 1;
399145b53394SDimitry Andric       }
399245b53394SDimitry Andric     } else if (Opts.ObjCAutoRefCount) {
399345b53394SDimitry Andric       Opts.ObjCWeak = Opts.ObjCWeakRuntime;
399413cc256eSDimitry Andric     }
3995180abc3dSDimitry Andric 
3996bfef3995SDimitry Andric     if (Args.hasArg(OPT_fobjc_subscripting_legacy_runtime))
3997bfef3995SDimitry Andric       Opts.ObjCSubscriptingLegacyRuntime =
3998bfef3995SDimitry Andric         (Opts.ObjCRuntime.getKind() == ObjCRuntime::FragileMacOSX);
3999180abc3dSDimitry Andric   }
4000180abc3dSDimitry Andric 
4001519fc96cSDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_fgnuc_version_EQ)) {
4002519fc96cSDimitry Andric     // Check that the version has 1 to 3 components and the minor and patch
4003519fc96cSDimitry Andric     // versions fit in two decimal digits.
4004519fc96cSDimitry Andric     VersionTuple GNUCVer;
4005519fc96cSDimitry Andric     bool Invalid = GNUCVer.tryParse(A->getValue());
4006519fc96cSDimitry Andric     unsigned Major = GNUCVer.getMajor();
4007145449b1SDimitry Andric     unsigned Minor = GNUCVer.getMinor().value_or(0);
4008145449b1SDimitry Andric     unsigned Patch = GNUCVer.getSubminor().value_or(0);
4009519fc96cSDimitry Andric     if (Invalid || GNUCVer.getBuild() || Minor >= 100 || Patch >= 100) {
4010519fc96cSDimitry Andric       Diags.Report(diag::err_drv_invalid_value)
4011519fc96cSDimitry Andric           << A->getAsString(Args) << A->getValue();
4012519fc96cSDimitry Andric     }
4013519fc96cSDimitry Andric     Opts.GNUCVersion = Major * 100 * 100 + Minor * 100 + Patch;
4014519fc96cSDimitry Andric   }
4015519fc96cSDimitry Andric 
4016145449b1SDimitry Andric   if (T.isOSAIX() && (Args.hasArg(OPT_mignore_xcoff_visibility)))
4017344a3780SDimitry Andric     Opts.IgnoreXCOFFVisibility = 1;
4018344a3780SDimitry Andric 
4019bca07a45SDimitry Andric   if (Args.hasArg(OPT_ftrapv)) {
40204ba67500SRoman Divacky     Opts.setSignedOverflowBehavior(LangOptions::SOB_Trapping);
4021bca07a45SDimitry Andric     // Set the handler, if one is specified.
4022bca07a45SDimitry Andric     Opts.OverflowHandler =
4023cfca06d7SDimitry Andric         std::string(Args.getLastArgValue(OPT_ftrapv_handler));
4024bca07a45SDimitry Andric   }
40254ba67500SRoman Divacky   else if (Args.hasArg(OPT_fwrapv))
40264ba67500SRoman Divacky     Opts.setSignedOverflowBehavior(LangOptions::SOB_Defined);
40271569ce68SRoman Divacky 
40285e20cdd8SDimitry Andric   Opts.MSCompatibilityVersion = 0;
40295e20cdd8SDimitry Andric   if (const Arg *A = Args.getLastArg(OPT_fms_compatibility_version)) {
40305e20cdd8SDimitry Andric     VersionTuple VT;
40315e20cdd8SDimitry Andric     if (VT.tryParse(A->getValue()))
40325e20cdd8SDimitry Andric       Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
40335e20cdd8SDimitry Andric                                                 << A->getValue();
40345e20cdd8SDimitry Andric     Opts.MSCompatibilityVersion = VT.getMajor() * 10000000 +
4035145449b1SDimitry Andric                                   VT.getMinor().value_or(0) * 100000 +
4036145449b1SDimitry Andric                                   VT.getSubminor().value_or(0);
40375e20cdd8SDimitry Andric   }
403806d4ba38SDimitry Andric 
4039676fbe81SDimitry Andric   // Mimicking gcc's behavior, trigraphs are only enabled if -trigraphs
404006d4ba38SDimitry Andric   // is specified, or -std is set to a conforming mode.
40414df029ccSDimitry Andric   // Trigraphs are disabled by default in C++17 and C23 onwards.
4042b60736ecSDimitry Andric   // For z/OS, trigraphs are enabled by default (without regard to the above).
4043b60736ecSDimitry Andric   Opts.Trigraphs =
40444df029ccSDimitry Andric       (!Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus17 && !Opts.C23) ||
40454df029ccSDimitry Andric       T.isOSzOS();
404606d4ba38SDimitry Andric   Opts.Trigraphs =
404706d4ba38SDimitry Andric       Args.hasFlag(OPT_ftrigraphs, OPT_fno_trigraphs, Opts.Trigraphs);
40481569ce68SRoman Divacky 
40492b6b257fSDimitry Andric   Opts.Blocks = Args.hasArg(OPT_fblocks) || (Opts.OpenCL
405048675466SDimitry Andric     && Opts.OpenCLVersion == 200);
4051461a67faSDimitry Andric 
40527fa27ce4SDimitry Andric   Opts.ConvergentFunctions = Args.hasArg(OPT_fconvergent_functions) ||
40537fa27ce4SDimitry Andric                              Opts.OpenCL || (Opts.CUDA && Opts.CUDAIsDevice) ||
4054ac9a064cSDimitry Andric                              Opts.SYCLIsDevice || Opts.HLSL;
4055706b4fc4SDimitry Andric 
40561569ce68SRoman Divacky   Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding;
405797b17066SDimitry Andric   if (!Opts.NoBuiltin)
405897b17066SDimitry Andric     getAllNoBuiltinFuncValues(Args, Opts.NoBuiltinFuncs);
4059145449b1SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_LongDouble_Group)) {
4060145449b1SDimitry Andric     if (A->getOption().matches(options::OPT_mlong_double_64))
4061145449b1SDimitry Andric       Opts.LongDoubleSize = 64;
4062145449b1SDimitry Andric     else if (A->getOption().matches(options::OPT_mlong_double_80))
4063145449b1SDimitry Andric       Opts.LongDoubleSize = 80;
4064145449b1SDimitry Andric     else if (A->getOption().matches(options::OPT_mlong_double_128))
4065145449b1SDimitry Andric       Opts.LongDoubleSize = 128;
4066145449b1SDimitry Andric     else
4067145449b1SDimitry Andric       Opts.LongDoubleSize = 0;
4068145449b1SDimitry Andric   }
4069e3b55780SDimitry Andric   if (Opts.FastRelaxedMath || Opts.CLUnsafeMath)
4070cfca06d7SDimitry Andric     Opts.setDefaultFPContractMode(LangOptions::FPM_Fast);
4071145449b1SDimitry Andric 
4072676fbe81SDimitry Andric   llvm::sort(Opts.ModuleFeatures);
4073b60736ecSDimitry Andric 
40742b6b257fSDimitry Andric   // -mrtd option
40752b6b257fSDimitry Andric   if (Arg *A = Args.getLastArg(OPT_mrtd)) {
40762b6b257fSDimitry Andric     if (Opts.getDefaultCallingConv() != LangOptions::DCC_None)
40772b6b257fSDimitry Andric       Diags.Report(diag::err_drv_argument_not_allowed_with)
40782b6b257fSDimitry Andric           << A->getSpelling() << "-fdefault-calling-conv";
40792b6b257fSDimitry Andric     else {
4080b1c73532SDimitry Andric       switch (T.getArch()) {
4081b1c73532SDimitry Andric       case llvm::Triple::x86:
4082b1c73532SDimitry Andric         Opts.setDefaultCallingConv(LangOptions::DCC_StdCall);
4083b1c73532SDimitry Andric         break;
4084b1c73532SDimitry Andric       case llvm::Triple::m68k:
4085b1c73532SDimitry Andric         Opts.setDefaultCallingConv(LangOptions::DCC_RtdCall);
4086b1c73532SDimitry Andric         break;
4087b1c73532SDimitry Andric       default:
40882b6b257fSDimitry Andric         Diags.Report(diag::err_drv_argument_not_allowed_with)
40892b6b257fSDimitry Andric             << A->getSpelling() << T.getTriple();
4090b1c73532SDimitry Andric       }
40912b6b257fSDimitry Andric     }
40922b6b257fSDimitry Andric   }
40932b6b257fSDimitry Andric 
4094344a3780SDimitry Andric   // Check if -fopenmp is specified and set default version to 5.0.
40957fa27ce4SDimitry Andric   Opts.OpenMP = Args.hasArg(OPT_fopenmp) ? 51 : 0;
409648675466SDimitry Andric   // Check if -fopenmp-simd is specified.
409748675466SDimitry Andric   bool IsSimdSpecified =
409848675466SDimitry Andric       Args.hasFlag(options::OPT_fopenmp_simd, options::OPT_fno_openmp_simd,
409948675466SDimitry Andric                    /*Default=*/false);
410048675466SDimitry Andric   Opts.OpenMPSimd = !Opts.OpenMP && IsSimdSpecified;
410151ece4aaSDimitry Andric   Opts.OpenMPUseTLS =
410251ece4aaSDimitry Andric       Opts.OpenMP && !Args.hasArg(options::OPT_fnoopenmp_use_tls);
41037fa27ce4SDimitry Andric   Opts.OpenMPIsTargetDevice =
41047fa27ce4SDimitry Andric       Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_is_target_device);
4105706b4fc4SDimitry Andric   Opts.OpenMPIRBuilder =
4106706b4fc4SDimitry Andric       Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_enable_irbuilder);
410748675466SDimitry Andric   bool IsTargetSpecified =
41087fa27ce4SDimitry Andric       Opts.OpenMPIsTargetDevice || Args.hasArg(options::OPT_fopenmp_targets_EQ);
410997b17066SDimitry Andric 
41107fa27ce4SDimitry Andric   Opts.ConvergentFunctions =
41117fa27ce4SDimitry Andric       Opts.ConvergentFunctions || Opts.OpenMPIsTargetDevice;
4112344a3780SDimitry Andric 
411348675466SDimitry Andric   if (Opts.OpenMP || Opts.OpenMPSimd) {
411448675466SDimitry Andric     if (int Version = getLastArgIntValue(
411548675466SDimitry Andric             Args, OPT_fopenmp_version_EQ,
41167fa27ce4SDimitry Andric             (IsSimdSpecified || IsTargetSpecified) ? 51 : Opts.OpenMP, Diags))
41172b6b257fSDimitry Andric       Opts.OpenMP = Version;
41182b6b257fSDimitry Andric     // Provide diagnostic when a given target is not expected to be an OpenMP
41192b6b257fSDimitry Andric     // device or host.
41207fa27ce4SDimitry Andric     if (!Opts.OpenMPIsTargetDevice) {
41212b6b257fSDimitry Andric       switch (T.getArch()) {
41222b6b257fSDimitry Andric       default:
41232b6b257fSDimitry Andric         break;
41242b6b257fSDimitry Andric       // Add unsupported host targets here:
41252b6b257fSDimitry Andric       case llvm::Triple::nvptx:
41262b6b257fSDimitry Andric       case llvm::Triple::nvptx64:
4127b60736ecSDimitry Andric         Diags.Report(diag::err_drv_omp_host_target_not_supported) << T.str();
41282b6b257fSDimitry Andric         break;
41292b6b257fSDimitry Andric       }
41302b6b257fSDimitry Andric     }
41312b6b257fSDimitry Andric   }
41322b6b257fSDimitry Andric 
4133461a67faSDimitry Andric   // Set the flag to prevent the implementation from emitting device exception
4134461a67faSDimitry Andric   // handling code for those requiring so.
41357fa27ce4SDimitry Andric   if ((Opts.OpenMPIsTargetDevice && (T.isNVPTX() || T.isAMDGCN())) ||
4136cfca06d7SDimitry Andric       Opts.OpenCLCPlusPlus) {
4137c0981da4SDimitry Andric 
4138461a67faSDimitry Andric     Opts.Exceptions = 0;
4139461a67faSDimitry Andric     Opts.CXXExceptions = 0;
4140461a67faSDimitry Andric   }
41417fa27ce4SDimitry Andric   if (Opts.OpenMPIsTargetDevice && T.isNVPTX()) {
4142676fbe81SDimitry Andric     Opts.OpenMPCUDANumSMs =
4143676fbe81SDimitry Andric         getLastArgIntValue(Args, options::OPT_fopenmp_cuda_number_of_sm_EQ,
4144676fbe81SDimitry Andric                            Opts.OpenMPCUDANumSMs, Diags);
4145676fbe81SDimitry Andric     Opts.OpenMPCUDABlocksPerSM =
4146676fbe81SDimitry Andric         getLastArgIntValue(Args, options::OPT_fopenmp_cuda_blocks_per_sm_EQ,
4147676fbe81SDimitry Andric                            Opts.OpenMPCUDABlocksPerSM, Diags);
414822989816SDimitry Andric     Opts.OpenMPCUDAReductionBufNum = getLastArgIntValue(
414922989816SDimitry Andric         Args, options::OPT_fopenmp_cuda_teams_reduction_recs_num_EQ,
415022989816SDimitry Andric         Opts.OpenMPCUDAReductionBufNum, Diags);
4151676fbe81SDimitry Andric   }
4152676fbe81SDimitry Andric 
4153c0981da4SDimitry Andric   // Set the value of the debugging flag used in the new offloading device RTL.
4154c0981da4SDimitry Andric   // Set either by a specific value or to a default if not specified.
41557fa27ce4SDimitry Andric   if (Opts.OpenMPIsTargetDevice && (Args.hasArg(OPT_fopenmp_target_debug) ||
4156c0981da4SDimitry Andric                                     Args.hasArg(OPT_fopenmp_target_debug_EQ))) {
4157c0981da4SDimitry Andric     Opts.OpenMPTargetDebug = getLastArgIntValue(
4158c0981da4SDimitry Andric         Args, OPT_fopenmp_target_debug_EQ, Opts.OpenMPTargetDebug, Diags);
4159c0981da4SDimitry Andric     if (!Opts.OpenMPTargetDebug && Args.hasArg(OPT_fopenmp_target_debug))
4160c0981da4SDimitry Andric       Opts.OpenMPTargetDebug = 1;
4161c0981da4SDimitry Andric   }
4162c0981da4SDimitry Andric 
41637fa27ce4SDimitry Andric   if (Opts.OpenMPIsTargetDevice) {
4164c0981da4SDimitry Andric     if (Args.hasArg(OPT_fopenmp_assume_teams_oversubscription))
4165c0981da4SDimitry Andric       Opts.OpenMPTeamSubscription = true;
4166c0981da4SDimitry Andric     if (Args.hasArg(OPT_fopenmp_assume_threads_oversubscription))
4167c0981da4SDimitry Andric       Opts.OpenMPThreadSubscription = true;
4168c0981da4SDimitry Andric   }
4169c0981da4SDimitry Andric 
417097b17066SDimitry Andric   // Get the OpenMP target triples if any.
41712b6b257fSDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_fopenmp_targets_EQ)) {
4172b60736ecSDimitry Andric     enum ArchPtrSize { Arch16Bit, Arch32Bit, Arch64Bit };
4173b60736ecSDimitry Andric     auto getArchPtrSize = [](const llvm::Triple &T) {
4174b60736ecSDimitry Andric       if (T.isArch16Bit())
4175b60736ecSDimitry Andric         return Arch16Bit;
4176b60736ecSDimitry Andric       if (T.isArch32Bit())
4177b60736ecSDimitry Andric         return Arch32Bit;
4178b60736ecSDimitry Andric       assert(T.isArch64Bit() && "Expected 64-bit architecture");
4179b60736ecSDimitry Andric       return Arch64Bit;
4180b60736ecSDimitry Andric     };
418197b17066SDimitry Andric 
418297b17066SDimitry Andric     for (unsigned i = 0; i < A->getNumValues(); ++i) {
418397b17066SDimitry Andric       llvm::Triple TT(A->getValue(i));
418497b17066SDimitry Andric 
4185461a67faSDimitry Andric       if (TT.getArch() == llvm::Triple::UnknownArch ||
4186b60736ecSDimitry Andric           !(TT.getArch() == llvm::Triple::aarch64 || TT.isPPC() ||
4187ac9a064cSDimitry Andric             TT.getArch() == llvm::Triple::systemz ||
4188461a67faSDimitry Andric             TT.getArch() == llvm::Triple::nvptx ||
4189461a67faSDimitry Andric             TT.getArch() == llvm::Triple::nvptx64 ||
4190cfca06d7SDimitry Andric             TT.getArch() == llvm::Triple::amdgcn ||
4191461a67faSDimitry Andric             TT.getArch() == llvm::Triple::x86 ||
4192461a67faSDimitry Andric             TT.getArch() == llvm::Triple::x86_64))
419348675466SDimitry Andric         Diags.Report(diag::err_drv_invalid_omp_target) << A->getValue(i);
4194b60736ecSDimitry Andric       else if (getArchPtrSize(T) != getArchPtrSize(TT))
4195b60736ecSDimitry Andric         Diags.Report(diag::err_drv_incompatible_omp_arch)
4196b60736ecSDimitry Andric             << A->getValue(i) << T.str();
419797b17066SDimitry Andric       else
419897b17066SDimitry Andric         Opts.OMPTargetTriples.push_back(TT);
419997b17066SDimitry Andric     }
420097b17066SDimitry Andric   }
420197b17066SDimitry Andric 
420297b17066SDimitry Andric   // Get OpenMP host file path if any and report if a non existent file is
420397b17066SDimitry Andric   // found
42042b6b257fSDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_fopenmp_host_ir_file_path)) {
420597b17066SDimitry Andric     Opts.OMPHostIRFile = A->getValue();
420697b17066SDimitry Andric     if (!llvm::sys::fs::exists(Opts.OMPHostIRFile))
420748675466SDimitry Andric       Diags.Report(diag::err_drv_omp_host_ir_file_not_found)
420897b17066SDimitry Andric           << Opts.OMPHostIRFile;
420997b17066SDimitry Andric   }
4210809500fcSDimitry Andric 
4211cfca06d7SDimitry Andric   // Set CUDA mode for OpenMP target NVPTX/AMDGCN if specified in options
42127fa27ce4SDimitry Andric   Opts.OpenMPCUDAMode = Opts.OpenMPIsTargetDevice &&
42137fa27ce4SDimitry Andric                         (T.isNVPTX() || T.isAMDGCN()) &&
421448675466SDimitry Andric                         Args.hasArg(options::OPT_fopenmp_cuda_mode);
421548675466SDimitry Andric 
4216b1c73532SDimitry Andric   // OpenACC Configuration.
4217b1c73532SDimitry Andric   if (Args.hasArg(options::OPT_fopenacc)) {
4218b1c73532SDimitry Andric     Opts.OpenACC = true;
4219b1c73532SDimitry Andric 
4220b1c73532SDimitry Andric     if (Arg *A = Args.getLastArg(options::OPT_openacc_macro_override))
4221b1c73532SDimitry Andric       Opts.OpenACCMacroOverride = A->getValue();
4222b1c73532SDimitry Andric   }
4223b1c73532SDimitry Andric 
42241569ce68SRoman Divacky   // FIXME: Eliminate this dependency.
422556d91b49SDimitry Andric   unsigned Opt = getOptimizationLevel(Args, IK, Diags),
42266a037251SDimitry Andric        OptSize = getOptimizationLevelSize(Args);
42271569ce68SRoman Divacky   Opts.Optimize = Opt != 0;
422856d91b49SDimitry Andric   Opts.OptimizeSize = OptSize != 0;
42291569ce68SRoman Divacky 
42301569ce68SRoman Divacky   // This is the __NO_INLINE__ define, which just depends on things like the
42311569ce68SRoman Divacky   // optimization level and -fno-inline, not actually whether the backend has
42321569ce68SRoman Divacky   // inlining enabled.
4233bab175ecSDimitry Andric   Opts.NoInlineDefine = !Opts.Optimize;
4234bab175ecSDimitry Andric   if (Arg *InlineArg = Args.getLastArg(
4235bab175ecSDimitry Andric           options::OPT_finline_functions, options::OPT_finline_hint_functions,
4236bab175ecSDimitry Andric           options::OPT_fno_inline_functions, options::OPT_fno_inline))
4237bab175ecSDimitry Andric     if (InlineArg->getOption().matches(options::OPT_fno_inline))
4238bab175ecSDimitry Andric       Opts.NoInlineDefine = true;
4239dbe13110SDimitry Andric 
42407442d6faSDimitry Andric   if (Arg *A = Args.getLastArg(OPT_ffp_contract)) {
42417442d6faSDimitry Andric     StringRef Val = A->getValue();
42427442d6faSDimitry Andric     if (Val == "fast")
4243cfca06d7SDimitry Andric       Opts.setDefaultFPContractMode(LangOptions::FPM_Fast);
42447442d6faSDimitry Andric     else if (Val == "on")
4245cfca06d7SDimitry Andric       Opts.setDefaultFPContractMode(LangOptions::FPM_On);
42467442d6faSDimitry Andric     else if (Val == "off")
4247cfca06d7SDimitry Andric       Opts.setDefaultFPContractMode(LangOptions::FPM_Off);
4248b60736ecSDimitry Andric     else if (Val == "fast-honor-pragmas")
4249b60736ecSDimitry Andric       Opts.setDefaultFPContractMode(LangOptions::FPM_FastHonorPragmas);
42507442d6faSDimitry Andric     else
42517442d6faSDimitry Andric       Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
42527442d6faSDimitry Andric   }
42537442d6faSDimitry Andric 
425413cc256eSDimitry Andric   // Parse -fsanitize= arguments.
425506d4ba38SDimitry Andric   parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ),
425606d4ba38SDimitry Andric                       Diags, Opts.Sanitize);
4257344a3780SDimitry Andric   Opts.NoSanitizeFiles = Args.getAllArgValues(OPT_fsanitize_ignorelist_EQ);
4258344a3780SDimitry Andric   std::vector<std::string> systemIgnorelists =
4259344a3780SDimitry Andric       Args.getAllArgValues(OPT_fsanitize_system_ignorelist_EQ);
4260344a3780SDimitry Andric   Opts.NoSanitizeFiles.insert(Opts.NoSanitizeFiles.end(),
4261344a3780SDimitry Andric                               systemIgnorelists.begin(),
4262344a3780SDimitry Andric                               systemIgnorelists.end());
42637442d6faSDimitry Andric 
426448675466SDimitry Andric   if (Arg *A = Args.getLastArg(OPT_fclang_abi_compat_EQ)) {
426548675466SDimitry Andric     Opts.setClangABICompat(LangOptions::ClangABI::Latest);
426648675466SDimitry Andric 
426748675466SDimitry Andric     StringRef Ver = A->getValue();
426848675466SDimitry Andric     std::pair<StringRef, StringRef> VerParts = Ver.split('.');
426948675466SDimitry Andric     unsigned Major, Minor = 0;
427048675466SDimitry Andric 
427148675466SDimitry Andric     // Check the version number is valid: either 3.x (0 <= x <= 9) or
427248675466SDimitry Andric     // y or y.0 (4 <= y <= current version).
4273312c0ed1SDimitry Andric     if (!VerParts.first.starts_with("0") &&
4274312c0ed1SDimitry Andric         !VerParts.first.getAsInteger(10, Major) && 3 <= Major &&
4275312c0ed1SDimitry Andric         Major <= CLANG_VERSION_MAJOR &&
4276312c0ed1SDimitry Andric         (Major == 3
4277312c0ed1SDimitry Andric              ? VerParts.second.size() == 1 &&
427848675466SDimitry Andric                    !VerParts.second.getAsInteger(10, Minor)
4279312c0ed1SDimitry Andric              : VerParts.first.size() == Ver.size() || VerParts.second == "0")) {
428048675466SDimitry Andric       // Got a valid version number.
428148675466SDimitry Andric       if (Major == 3 && Minor <= 8)
428248675466SDimitry Andric         Opts.setClangABICompat(LangOptions::ClangABI::Ver3_8);
428348675466SDimitry Andric       else if (Major <= 4)
428448675466SDimitry Andric         Opts.setClangABICompat(LangOptions::ClangABI::Ver4);
428548675466SDimitry Andric       else if (Major <= 6)
428648675466SDimitry Andric         Opts.setClangABICompat(LangOptions::ClangABI::Ver6);
4287676fbe81SDimitry Andric       else if (Major <= 7)
4288676fbe81SDimitry Andric         Opts.setClangABICompat(LangOptions::ClangABI::Ver7);
4289519fc96cSDimitry Andric       else if (Major <= 9)
4290519fc96cSDimitry Andric         Opts.setClangABICompat(LangOptions::ClangABI::Ver9);
4291b60736ecSDimitry Andric       else if (Major <= 11)
4292b60736ecSDimitry Andric         Opts.setClangABICompat(LangOptions::ClangABI::Ver11);
4293344a3780SDimitry Andric       else if (Major <= 12)
4294344a3780SDimitry Andric         Opts.setClangABICompat(LangOptions::ClangABI::Ver12);
4295145449b1SDimitry Andric       else if (Major <= 14)
4296145449b1SDimitry Andric         Opts.setClangABICompat(LangOptions::ClangABI::Ver14);
4297e3b55780SDimitry Andric       else if (Major <= 15)
4298e3b55780SDimitry Andric         Opts.setClangABICompat(LangOptions::ClangABI::Ver15);
4299b1c73532SDimitry Andric       else if (Major <= 17)
4300b1c73532SDimitry Andric         Opts.setClangABICompat(LangOptions::ClangABI::Ver17);
4301ac9a064cSDimitry Andric       else if (Major <= 18)
4302ac9a064cSDimitry Andric         Opts.setClangABICompat(LangOptions::ClangABI::Ver18);
430348675466SDimitry Andric     } else if (Ver != "latest") {
430448675466SDimitry Andric       Diags.Report(diag::err_drv_invalid_value)
430548675466SDimitry Andric           << A->getAsString(Args) << A->getValue();
430648675466SDimitry Andric     }
430748675466SDimitry Andric   }
430848675466SDimitry Andric 
4309cfca06d7SDimitry Andric   if (Arg *A = Args.getLastArg(OPT_msign_return_address_EQ)) {
4310cfca06d7SDimitry Andric     StringRef SignScope = A->getValue();
4311cfca06d7SDimitry Andric 
4312344a3780SDimitry Andric     if (SignScope.equals_insensitive("none"))
4313cfca06d7SDimitry Andric       Opts.setSignReturnAddressScope(
4314cfca06d7SDimitry Andric           LangOptions::SignReturnAddressScopeKind::None);
4315344a3780SDimitry Andric     else if (SignScope.equals_insensitive("all"))
4316cfca06d7SDimitry Andric       Opts.setSignReturnAddressScope(
4317cfca06d7SDimitry Andric           LangOptions::SignReturnAddressScopeKind::All);
4318344a3780SDimitry Andric     else if (SignScope.equals_insensitive("non-leaf"))
4319cfca06d7SDimitry Andric       Opts.setSignReturnAddressScope(
4320cfca06d7SDimitry Andric           LangOptions::SignReturnAddressScopeKind::NonLeaf);
4321cfca06d7SDimitry Andric     else
4322cfca06d7SDimitry Andric       Diags.Report(diag::err_drv_invalid_value)
4323cfca06d7SDimitry Andric           << A->getAsString(Args) << SignScope;
4324cfca06d7SDimitry Andric 
4325cfca06d7SDimitry Andric     if (Arg *A = Args.getLastArg(OPT_msign_return_address_key_EQ)) {
4326cfca06d7SDimitry Andric       StringRef SignKey = A->getValue();
4327cfca06d7SDimitry Andric       if (!SignScope.empty() && !SignKey.empty()) {
4328b1c73532SDimitry Andric         if (SignKey == "a_key")
4329cfca06d7SDimitry Andric           Opts.setSignReturnAddressKey(
4330cfca06d7SDimitry Andric               LangOptions::SignReturnAddressKeyKind::AKey);
4331b1c73532SDimitry Andric         else if (SignKey == "b_key")
4332cfca06d7SDimitry Andric           Opts.setSignReturnAddressKey(
4333cfca06d7SDimitry Andric               LangOptions::SignReturnAddressKeyKind::BKey);
4334cfca06d7SDimitry Andric         else
4335cfca06d7SDimitry Andric           Diags.Report(diag::err_drv_invalid_value)
4336cfca06d7SDimitry Andric               << A->getAsString(Args) << SignKey;
4337cfca06d7SDimitry Andric       }
4338cfca06d7SDimitry Andric     }
4339cfca06d7SDimitry Andric   }
4340cfca06d7SDimitry Andric 
4341344a3780SDimitry Andric   // The value can be empty, which indicates the system default should be used.
4342344a3780SDimitry Andric   StringRef CXXABI = Args.getLastArgValue(OPT_fcxx_abi_EQ);
4343344a3780SDimitry Andric   if (!CXXABI.empty()) {
4344344a3780SDimitry Andric     if (!TargetCXXABI::isABI(CXXABI)) {
4345344a3780SDimitry Andric       Diags.Report(diag::err_invalid_cxx_abi) << CXXABI;
4346344a3780SDimitry Andric     } else {
4347344a3780SDimitry Andric       auto Kind = TargetCXXABI::getKind(CXXABI);
4348344a3780SDimitry Andric       if (!TargetCXXABI::isSupportedCXXABI(T, Kind))
4349344a3780SDimitry Andric         Diags.Report(diag::err_unsupported_cxx_abi) << CXXABI << T.str();
4350344a3780SDimitry Andric       else
4351344a3780SDimitry Andric         Opts.CXXABI = Kind;
4352344a3780SDimitry Andric     }
4353344a3780SDimitry Andric   }
4354344a3780SDimitry Andric 
4355344a3780SDimitry Andric   Opts.RelativeCXXABIVTables =
4356344a3780SDimitry Andric       Args.hasFlag(options::OPT_fexperimental_relative_cxx_abi_vtables,
4357344a3780SDimitry Andric                    options::OPT_fno_experimental_relative_cxx_abi_vtables,
4358344a3780SDimitry Andric                    TargetCXXABI::usesRelativeVTables(T));
4359344a3780SDimitry Andric 
4360b1c73532SDimitry Andric   // RTTI is on by default.
4361b1c73532SDimitry Andric   bool HasRTTI = !Args.hasArg(options::OPT_fno_rtti);
4362b1c73532SDimitry Andric   Opts.OmitVTableRTTI =
4363b1c73532SDimitry Andric       Args.hasFlag(options::OPT_fexperimental_omit_vtable_rtti,
4364b1c73532SDimitry Andric                    options::OPT_fno_experimental_omit_vtable_rtti, false);
4365b1c73532SDimitry Andric   if (Opts.OmitVTableRTTI && HasRTTI)
4366b1c73532SDimitry Andric     Diags.Report(diag::err_drv_using_omit_rtti_component_without_no_rtti);
4367b1c73532SDimitry Andric 
4368c0981da4SDimitry Andric   for (const auto &A : Args.getAllArgValues(OPT_fmacro_prefix_map_EQ)) {
4369c0981da4SDimitry Andric     auto Split = StringRef(A).split('=');
4370c0981da4SDimitry Andric     Opts.MacroPrefixMap.insert(
4371c0981da4SDimitry Andric         {std::string(Split.first), std::string(Split.second)});
4372c0981da4SDimitry Andric   }
4373c0981da4SDimitry Andric 
4374145449b1SDimitry Andric   Opts.UseTargetPathSeparator =
4375145449b1SDimitry Andric       !Args.getLastArg(OPT_fno_file_reproducible) &&
4376145449b1SDimitry Andric       (Args.getLastArg(OPT_ffile_compilation_dir_EQ) ||
4377145449b1SDimitry Andric        Args.getLastArg(OPT_fmacro_prefix_map_EQ) ||
4378145449b1SDimitry Andric        Args.getLastArg(OPT_ffile_reproducible));
4379145449b1SDimitry Andric 
438077fc4c14SDimitry Andric   // Error if -mvscale-min is unbounded.
438177fc4c14SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_mvscale_min_EQ)) {
438277fc4c14SDimitry Andric     unsigned VScaleMin;
438377fc4c14SDimitry Andric     if (StringRef(A->getValue()).getAsInteger(10, VScaleMin) || VScaleMin == 0)
438477fc4c14SDimitry Andric       Diags.Report(diag::err_cc1_unbounded_vscale_min);
438577fc4c14SDimitry Andric   }
438677fc4c14SDimitry Andric 
4387145449b1SDimitry Andric   if (const Arg *A = Args.getLastArg(OPT_frandomize_layout_seed_file_EQ)) {
4388145449b1SDimitry Andric     std::ifstream SeedFile(A->getValue(0));
4389145449b1SDimitry Andric 
4390145449b1SDimitry Andric     if (!SeedFile.is_open())
4391145449b1SDimitry Andric       Diags.Report(diag::err_drv_cannot_open_randomize_layout_seed_file)
4392145449b1SDimitry Andric           << A->getValue(0);
4393145449b1SDimitry Andric 
4394145449b1SDimitry Andric     std::getline(SeedFile, Opts.RandstructSeed);
4395145449b1SDimitry Andric   }
4396145449b1SDimitry Andric 
4397145449b1SDimitry Andric   if (const Arg *A = Args.getLastArg(OPT_frandomize_layout_seed_EQ))
4398145449b1SDimitry Andric     Opts.RandstructSeed = A->getValue(0);
4399145449b1SDimitry Andric 
4400e3b55780SDimitry Andric   // Validate options for HLSL
4401e3b55780SDimitry Andric   if (Opts.HLSL) {
4402b1c73532SDimitry Andric     // TODO: Revisit restricting SPIR-V to logical once we've figured out how to
4403b1c73532SDimitry Andric     // handle PhysicalStorageBuffer64 memory model
4404b1c73532SDimitry Andric     if (T.isDXIL() || T.isSPIRVLogical()) {
44054df029ccSDimitry Andric       enum { ShaderModel, VulkanEnv, ShaderStage };
44064df029ccSDimitry Andric       enum { OS, Environment };
44074df029ccSDimitry Andric 
44084df029ccSDimitry Andric       int ExpectedOS = T.isSPIRVLogical() ? VulkanEnv : ShaderModel;
44094df029ccSDimitry Andric 
4410b1c73532SDimitry Andric       if (T.getOSName().empty()) {
4411b1c73532SDimitry Andric         Diags.Report(diag::err_drv_hlsl_bad_shader_required_in_target)
44124df029ccSDimitry Andric             << ExpectedOS << OS << T.str();
4413b1c73532SDimitry Andric       } else if (T.getEnvironmentName().empty()) {
4414b1c73532SDimitry Andric         Diags.Report(diag::err_drv_hlsl_bad_shader_required_in_target)
44154df029ccSDimitry Andric             << ShaderStage << Environment << T.str();
4416b1c73532SDimitry Andric       } else if (!T.isShaderStageEnvironment()) {
4417b1c73532SDimitry Andric         Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported)
4418b1c73532SDimitry Andric             << ShaderStage << T.getEnvironmentName() << T.str();
4419b1c73532SDimitry Andric       }
44204df029ccSDimitry Andric 
44214df029ccSDimitry Andric       if (T.isDXIL()) {
44224df029ccSDimitry Andric         if (!T.isShaderModelOS() || T.getOSVersion() == VersionTuple(0)) {
44234df029ccSDimitry Andric           Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported)
44244df029ccSDimitry Andric               << ShaderModel << T.getOSName() << T.str();
44254df029ccSDimitry Andric         }
4426ac9a064cSDimitry Andric         // Validate that if fnative-half-type is given, that
4427ac9a064cSDimitry Andric         // the language standard is at least hlsl2018, and that
4428ac9a064cSDimitry Andric         // the target shader model is at least 6.2.
4429ac9a064cSDimitry Andric         if (Args.getLastArg(OPT_fnative_half_type)) {
4430ac9a064cSDimitry Andric           const LangStandard &Std =
4431ac9a064cSDimitry Andric               LangStandard::getLangStandardForKind(Opts.LangStd);
4432ac9a064cSDimitry Andric           if (!(Opts.LangStd >= LangStandard::lang_hlsl2018 &&
4433ac9a064cSDimitry Andric                 T.getOSVersion() >= VersionTuple(6, 2)))
4434ac9a064cSDimitry Andric             Diags.Report(diag::err_drv_hlsl_16bit_types_unsupported)
4435ac9a064cSDimitry Andric                 << "-enable-16bit-types" << true << Std.getName()
4436ac9a064cSDimitry Andric                 << T.getOSVersion().getAsString();
4437ac9a064cSDimitry Andric         }
44384df029ccSDimitry Andric       } else if (T.isSPIRVLogical()) {
44394df029ccSDimitry Andric         if (!T.isVulkanOS() || T.getVulkanVersion() == VersionTuple(0)) {
44404df029ccSDimitry Andric           Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported)
44414df029ccSDimitry Andric               << VulkanEnv << T.getOSName() << T.str();
44424df029ccSDimitry Andric         }
4443ac9a064cSDimitry Andric         if (Args.getLastArg(OPT_fnative_half_type)) {
4444ac9a064cSDimitry Andric           const LangStandard &Std =
4445ac9a064cSDimitry Andric               LangStandard::getLangStandardForKind(Opts.LangStd);
4446ac9a064cSDimitry Andric           if (!(Opts.LangStd >= LangStandard::lang_hlsl2018))
4447ac9a064cSDimitry Andric             Diags.Report(diag::err_drv_hlsl_16bit_types_unsupported)
4448ac9a064cSDimitry Andric                 << "-fnative-half-type" << false << Std.getName();
4449ac9a064cSDimitry Andric         }
44504df029ccSDimitry Andric       } else {
44514df029ccSDimitry Andric         llvm_unreachable("expected DXIL or SPIR-V target");
44524df029ccSDimitry Andric       }
4453b1c73532SDimitry Andric     } else
4454e3b55780SDimitry Andric       Diags.Report(diag::err_drv_hlsl_unsupported_target) << T.str();
4455e3b55780SDimitry Andric   }
4456e3b55780SDimitry Andric 
4457344a3780SDimitry Andric   return Diags.getNumErrors() == NumErrorsBefore;
44581569ce68SRoman Divacky }
44591569ce68SRoman Divacky 
isStrictlyPreprocessorAction(frontend::ActionKind Action)4460ef915aabSDimitry Andric static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {
4461ef915aabSDimitry Andric   switch (Action) {
4462ef915aabSDimitry Andric   case frontend::ASTDeclList:
4463ef915aabSDimitry Andric   case frontend::ASTDump:
4464ef915aabSDimitry Andric   case frontend::ASTPrint:
4465ef915aabSDimitry Andric   case frontend::ASTView:
4466ef915aabSDimitry Andric   case frontend::EmitAssembly:
4467ef915aabSDimitry Andric   case frontend::EmitBC:
4468ac9a064cSDimitry Andric   case frontend::EmitCIR:
4469ef915aabSDimitry Andric   case frontend::EmitHTML:
4470ef915aabSDimitry Andric   case frontend::EmitLLVM:
4471ef915aabSDimitry Andric   case frontend::EmitLLVMOnly:
4472ef915aabSDimitry Andric   case frontend::EmitCodeGenOnly:
4473ef915aabSDimitry Andric   case frontend::EmitObj:
44746f8fc217SDimitry Andric   case frontend::ExtractAPI:
4475ef915aabSDimitry Andric   case frontend::FixIt:
4476ef915aabSDimitry Andric   case frontend::GenerateModule:
4477ef915aabSDimitry Andric   case frontend::GenerateModuleInterface:
4478ac9a064cSDimitry Andric   case frontend::GenerateReducedModuleInterface:
4479145449b1SDimitry Andric   case frontend::GenerateHeaderUnit:
4480ef915aabSDimitry Andric   case frontend::GeneratePCH:
4481cfca06d7SDimitry Andric   case frontend::GenerateInterfaceStubs:
4482ef915aabSDimitry Andric   case frontend::ParseSyntaxOnly:
4483ef915aabSDimitry Andric   case frontend::ModuleFileInfo:
4484ef915aabSDimitry Andric   case frontend::VerifyPCH:
4485ef915aabSDimitry Andric   case frontend::PluginAction:
4486ef915aabSDimitry Andric   case frontend::RewriteObjC:
4487ef915aabSDimitry Andric   case frontend::RewriteTest:
4488ef915aabSDimitry Andric   case frontend::RunAnalysis:
448948675466SDimitry Andric   case frontend::TemplightDump:
4490ef915aabSDimitry Andric   case frontend::MigrateSource:
4491ef915aabSDimitry Andric     return false;
4492ef915aabSDimitry Andric 
449348675466SDimitry Andric   case frontend::DumpCompilerOptions:
4494ef915aabSDimitry Andric   case frontend::DumpRawTokens:
4495ef915aabSDimitry Andric   case frontend::DumpTokens:
4496ef915aabSDimitry Andric   case frontend::InitOnly:
4497ef915aabSDimitry Andric   case frontend::PrintPreamble:
4498ef915aabSDimitry Andric   case frontend::PrintPreprocessedInput:
4499ef915aabSDimitry Andric   case frontend::RewriteMacros:
4500ef915aabSDimitry Andric   case frontend::RunPreprocessorOnly:
450122989816SDimitry Andric   case frontend::PrintDependencyDirectivesSourceMinimizerOutput:
4502ef915aabSDimitry Andric     return true;
4503ef915aabSDimitry Andric   }
4504ef915aabSDimitry Andric   llvm_unreachable("invalid frontend action");
4505ef915aabSDimitry Andric }
4506ef915aabSDimitry Andric 
GeneratePreprocessorArgs(const PreprocessorOptions & Opts,ArgumentConsumer Consumer,const LangOptions & LangOpts,const FrontendOptions & FrontendOpts,const CodeGenOptions & CodeGenOpts)4507b1c73532SDimitry Andric static void GeneratePreprocessorArgs(const PreprocessorOptions &Opts,
4508b1c73532SDimitry Andric                                      ArgumentConsumer Consumer,
4509344a3780SDimitry Andric                                      const LangOptions &LangOpts,
4510344a3780SDimitry Andric                                      const FrontendOptions &FrontendOpts,
4511344a3780SDimitry Andric                                      const CodeGenOptions &CodeGenOpts) {
4512b1c73532SDimitry Andric   const PreprocessorOptions *PreprocessorOpts = &Opts;
4513344a3780SDimitry Andric 
45147fa27ce4SDimitry Andric #define PREPROCESSOR_OPTION_WITH_MARSHALLING(...)                              \
4515b1c73532SDimitry Andric   GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
4516344a3780SDimitry Andric #include "clang/Driver/Options.inc"
4517344a3780SDimitry Andric #undef PREPROCESSOR_OPTION_WITH_MARSHALLING
4518344a3780SDimitry Andric 
4519344a3780SDimitry Andric   if (Opts.PCHWithHdrStop && !Opts.PCHWithHdrStopCreate)
4520b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_pch_through_hdrstop_use);
4521344a3780SDimitry Andric 
4522344a3780SDimitry Andric   for (const auto &D : Opts.DeserializedPCHDeclsToErrorOn)
4523b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_error_on_deserialized_pch_decl, D);
4524344a3780SDimitry Andric 
4525344a3780SDimitry Andric   if (Opts.PrecompiledPreambleBytes != std::make_pair(0u, false))
4526b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_preamble_bytes_EQ,
4527344a3780SDimitry Andric                 Twine(Opts.PrecompiledPreambleBytes.first) + "," +
4528b1c73532SDimitry Andric                     (Opts.PrecompiledPreambleBytes.second ? "1" : "0"));
4529344a3780SDimitry Andric 
4530344a3780SDimitry Andric   for (const auto &M : Opts.Macros) {
4531344a3780SDimitry Andric     // Don't generate __CET__ macro definitions. They are implied by the
4532344a3780SDimitry Andric     // -fcf-protection option that is generated elsewhere.
4533344a3780SDimitry Andric     if (M.first == "__CET__=1" && !M.second &&
4534344a3780SDimitry Andric         !CodeGenOpts.CFProtectionReturn && CodeGenOpts.CFProtectionBranch)
4535344a3780SDimitry Andric       continue;
4536344a3780SDimitry Andric     if (M.first == "__CET__=2" && !M.second && CodeGenOpts.CFProtectionReturn &&
4537344a3780SDimitry Andric         !CodeGenOpts.CFProtectionBranch)
4538344a3780SDimitry Andric       continue;
4539344a3780SDimitry Andric     if (M.first == "__CET__=3" && !M.second && CodeGenOpts.CFProtectionReturn &&
4540344a3780SDimitry Andric         CodeGenOpts.CFProtectionBranch)
4541344a3780SDimitry Andric       continue;
4542344a3780SDimitry Andric 
4543b1c73532SDimitry Andric     GenerateArg(Consumer, M.second ? OPT_U : OPT_D, M.first);
4544344a3780SDimitry Andric   }
4545344a3780SDimitry Andric 
4546344a3780SDimitry Andric   for (const auto &I : Opts.Includes) {
4547344a3780SDimitry Andric     // Don't generate OpenCL includes. They are implied by other flags that are
4548344a3780SDimitry Andric     // generated elsewhere.
4549344a3780SDimitry Andric     if (LangOpts.OpenCL && LangOpts.IncludeDefaultHeader &&
4550344a3780SDimitry Andric         ((LangOpts.DeclareOpenCLBuiltins && I == "opencl-c-base.h") ||
4551344a3780SDimitry Andric          I == "opencl-c.h"))
4552344a3780SDimitry Andric       continue;
4553145449b1SDimitry Andric     // Don't generate HLSL includes. They are implied by other flags that are
4554145449b1SDimitry Andric     // generated elsewhere.
4555145449b1SDimitry Andric     if (LangOpts.HLSL && I == "hlsl.h")
4556145449b1SDimitry Andric       continue;
4557344a3780SDimitry Andric 
4558b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_include, I);
4559344a3780SDimitry Andric   }
4560344a3780SDimitry Andric 
4561344a3780SDimitry Andric   for (const auto &CI : Opts.ChainedIncludes)
4562b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_chain_include, CI);
4563344a3780SDimitry Andric 
4564344a3780SDimitry Andric   for (const auto &RF : Opts.RemappedFiles)
4565b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_remap_file, RF.first + ";" + RF.second);
4566344a3780SDimitry Andric 
4567e3b55780SDimitry Andric   if (Opts.SourceDateEpoch)
4568b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_source_date_epoch, Twine(*Opts.SourceDateEpoch));
4569b1c73532SDimitry Andric 
4570b1c73532SDimitry Andric   if (Opts.DefineTargetOSMacros)
4571b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fdefine_target_os_macros);
4572e3b55780SDimitry Andric 
4573ac9a064cSDimitry Andric   for (const auto &EmbedEntry : Opts.EmbedEntries)
4574ac9a064cSDimitry Andric     GenerateArg(Consumer, OPT_embed_dir_EQ, EmbedEntry);
4575ac9a064cSDimitry Andric 
4576344a3780SDimitry Andric   // Don't handle LexEditorPlaceholders. It is implied by the action that is
4577344a3780SDimitry Andric   // generated elsewhere.
4578344a3780SDimitry Andric }
4579344a3780SDimitry Andric 
ParsePreprocessorArgs(PreprocessorOptions & Opts,ArgList & Args,DiagnosticsEngine & Diags,frontend::ActionKind Action,const FrontendOptions & FrontendOpts)4580344a3780SDimitry Andric static bool ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
4581ef915aabSDimitry Andric                                   DiagnosticsEngine &Diags,
4582344a3780SDimitry Andric                                   frontend::ActionKind Action,
4583344a3780SDimitry Andric                                   const FrontendOptions &FrontendOpts) {
4584344a3780SDimitry Andric   unsigned NumErrorsBefore = Diags.getNumErrors();
4585344a3780SDimitry Andric 
4586344a3780SDimitry Andric   PreprocessorOptions *PreprocessorOpts = &Opts;
4587344a3780SDimitry Andric 
45887fa27ce4SDimitry Andric #define PREPROCESSOR_OPTION_WITH_MARSHALLING(...)                              \
45897fa27ce4SDimitry Andric   PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
4590344a3780SDimitry Andric #include "clang/Driver/Options.inc"
4591344a3780SDimitry Andric #undef PREPROCESSOR_OPTION_WITH_MARSHALLING
4592344a3780SDimitry Andric 
4593676fbe81SDimitry Andric   Opts.PCHWithHdrStop = Args.hasArg(OPT_pch_through_hdrstop_create) ||
4594676fbe81SDimitry Andric                         Args.hasArg(OPT_pch_through_hdrstop_use);
45953d1dcd9bSDimitry Andric 
459648675466SDimitry Andric   for (const auto *A : Args.filtered(OPT_error_on_deserialized_pch_decl))
459713cc256eSDimitry Andric     Opts.DeserializedPCHDeclsToErrorOn.insert(A->getValue());
4598bca07a45SDimitry Andric 
45993d1dcd9bSDimitry Andric   if (const Arg *A = Args.getLastArg(OPT_preamble_bytes_EQ)) {
460013cc256eSDimitry Andric     StringRef Value(A->getValue());
46013d1dcd9bSDimitry Andric     size_t Comma = Value.find(',');
46023d1dcd9bSDimitry Andric     unsigned Bytes = 0;
46033d1dcd9bSDimitry Andric     unsigned EndOfLine = 0;
46043d1dcd9bSDimitry Andric 
460536981b17SDimitry Andric     if (Comma == StringRef::npos ||
46063d1dcd9bSDimitry Andric         Value.substr(0, Comma).getAsInteger(10, Bytes) ||
46073d1dcd9bSDimitry Andric         Value.substr(Comma + 1).getAsInteger(10, EndOfLine))
46083d1dcd9bSDimitry Andric       Diags.Report(diag::err_drv_preamble_format);
46093d1dcd9bSDimitry Andric     else {
46103d1dcd9bSDimitry Andric       Opts.PrecompiledPreambleBytes.first = Bytes;
46113d1dcd9bSDimitry Andric       Opts.PrecompiledPreambleBytes.second = (EndOfLine != 0);
46123d1dcd9bSDimitry Andric     }
46133d1dcd9bSDimitry Andric   }
46143d1dcd9bSDimitry Andric 
461548675466SDimitry Andric   // Add the __CET__ macro if a CFProtection option is set.
461648675466SDimitry Andric   if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) {
461748675466SDimitry Andric     StringRef Name = A->getValue();
461848675466SDimitry Andric     if (Name == "branch")
461948675466SDimitry Andric       Opts.addMacroDef("__CET__=1");
462048675466SDimitry Andric     else if (Name == "return")
462148675466SDimitry Andric       Opts.addMacroDef("__CET__=2");
462248675466SDimitry Andric     else if (Name == "full")
462348675466SDimitry Andric       Opts.addMacroDef("__CET__=3");
462448675466SDimitry Andric   }
462548675466SDimitry Andric 
46261569ce68SRoman Divacky   // Add macros from the command line.
462748675466SDimitry Andric   for (const auto *A : Args.filtered(OPT_D, OPT_U)) {
4628798321d8SDimitry Andric     if (A->getOption().matches(OPT_D))
4629798321d8SDimitry Andric       Opts.addMacroDef(A->getValue());
46301569ce68SRoman Divacky     else
4631798321d8SDimitry Andric       Opts.addMacroUndef(A->getValue());
46321569ce68SRoman Divacky   }
46331569ce68SRoman Divacky 
46341569ce68SRoman Divacky   // Add the ordered list of -includes.
463548675466SDimitry Andric   for (const auto *A : Args.filtered(OPT_include))
4636798321d8SDimitry Andric     Opts.Includes.emplace_back(A->getValue());
463734d02d0bSRoman Divacky 
463848675466SDimitry Andric   for (const auto *A : Args.filtered(OPT_chain_include))
4639798321d8SDimitry Andric     Opts.ChainedIncludes.emplace_back(A->getValue());
464001af97d3SDimitry Andric 
464148675466SDimitry Andric   for (const auto *A : Args.filtered(OPT_remap_file)) {
4642798321d8SDimitry Andric     std::pair<StringRef, StringRef> Split = StringRef(A->getValue()).split(';');
464334d02d0bSRoman Divacky 
464434d02d0bSRoman Divacky     if (Split.second.empty()) {
46454ba67500SRoman Divacky       Diags.Report(diag::err_drv_invalid_remap_file) << A->getAsString(Args);
464634d02d0bSRoman Divacky       continue;
464734d02d0bSRoman Divacky     }
464834d02d0bSRoman Divacky 
464934d02d0bSRoman Divacky     Opts.addRemappedFile(Split.first, Split.second);
465034d02d0bSRoman Divacky   }
4651180abc3dSDimitry Andric 
4652e3b55780SDimitry Andric   if (const Arg *A = Args.getLastArg(OPT_source_date_epoch)) {
4653e3b55780SDimitry Andric     StringRef Epoch = A->getValue();
4654e3b55780SDimitry Andric     // SOURCE_DATE_EPOCH, if specified, must be a non-negative decimal integer.
4655e3b55780SDimitry Andric     // On time64 systems, pick 253402300799 (the UNIX timestamp of
4656e3b55780SDimitry Andric     // 9999-12-31T23:59:59Z) as the upper bound.
4657e3b55780SDimitry Andric     const uint64_t MaxTimestamp =
4658e3b55780SDimitry Andric         std::min<uint64_t>(std::numeric_limits<time_t>::max(), 253402300799);
4659e3b55780SDimitry Andric     uint64_t V;
4660e3b55780SDimitry Andric     if (Epoch.getAsInteger(10, V) || V > MaxTimestamp) {
4661e3b55780SDimitry Andric       Diags.Report(diag::err_fe_invalid_source_date_epoch)
4662e3b55780SDimitry Andric           << Epoch << MaxTimestamp;
4663e3b55780SDimitry Andric     } else {
4664e3b55780SDimitry Andric       Opts.SourceDateEpoch = V;
4665e3b55780SDimitry Andric     }
4666e3b55780SDimitry Andric   }
4667e3b55780SDimitry Andric 
4668ac9a064cSDimitry Andric   for (const auto *A : Args.filtered(OPT_embed_dir_EQ)) {
4669ac9a064cSDimitry Andric     StringRef Val = A->getValue();
4670ac9a064cSDimitry Andric     Opts.EmbedEntries.push_back(std::string(Val));
4671ac9a064cSDimitry Andric   }
4672ac9a064cSDimitry Andric 
4673ef915aabSDimitry Andric   // Always avoid lexing editor placeholders when we're just running the
4674ef915aabSDimitry Andric   // preprocessor as we never want to emit the
4675ef915aabSDimitry Andric   // "editor placeholder in source file" error in PP only mode.
4676ef915aabSDimitry Andric   if (isStrictlyPreprocessorAction(Action))
4677ef915aabSDimitry Andric     Opts.LexEditorPlaceholders = false;
4678344a3780SDimitry Andric 
4679b1c73532SDimitry Andric   Opts.DefineTargetOSMacros =
4680b1c73532SDimitry Andric       Args.hasFlag(OPT_fdefine_target_os_macros,
4681b1c73532SDimitry Andric                    OPT_fno_define_target_os_macros, Opts.DefineTargetOSMacros);
4682b1c73532SDimitry Andric 
4683344a3780SDimitry Andric   return Diags.getNumErrors() == NumErrorsBefore;
46841569ce68SRoman Divacky }
46851569ce68SRoman Divacky 
4686b1c73532SDimitry Andric static void
GeneratePreprocessorOutputArgs(const PreprocessorOutputOptions & Opts,ArgumentConsumer Consumer,frontend::ActionKind Action)4687b1c73532SDimitry Andric GeneratePreprocessorOutputArgs(const PreprocessorOutputOptions &Opts,
4688b1c73532SDimitry Andric                                ArgumentConsumer Consumer,
4689b1c73532SDimitry Andric                                frontend::ActionKind Action) {
4690344a3780SDimitry Andric   const PreprocessorOutputOptions &PreprocessorOutputOpts = Opts;
4691344a3780SDimitry Andric 
46927fa27ce4SDimitry Andric #define PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING(...)                       \
4693b1c73532SDimitry Andric   GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
4694344a3780SDimitry Andric #include "clang/Driver/Options.inc"
4695344a3780SDimitry Andric #undef PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING
4696344a3780SDimitry Andric 
4697344a3780SDimitry Andric   bool Generate_dM = isStrictlyPreprocessorAction(Action) && !Opts.ShowCPP;
4698344a3780SDimitry Andric   if (Generate_dM)
4699b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_dM);
4700344a3780SDimitry Andric   if (!Generate_dM && Opts.ShowMacros)
4701b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_dD);
4702145449b1SDimitry Andric   if (Opts.DirectivesOnly)
4703b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_fdirectives_only);
4704344a3780SDimitry Andric }
4705344a3780SDimitry Andric 
ParsePreprocessorOutputArgs(PreprocessorOutputOptions & Opts,ArgList & Args,DiagnosticsEngine & Diags,frontend::ActionKind Action)4706344a3780SDimitry Andric static bool ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
4707344a3780SDimitry Andric                                         ArgList &Args, DiagnosticsEngine &Diags,
4708809500fcSDimitry Andric                                         frontend::ActionKind Action) {
4709344a3780SDimitry Andric   unsigned NumErrorsBefore = Diags.getNumErrors();
4710809500fcSDimitry Andric 
4711344a3780SDimitry Andric   PreprocessorOutputOptions &PreprocessorOutputOpts = Opts;
4712344a3780SDimitry Andric 
47137fa27ce4SDimitry Andric #define PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING(...)                       \
47147fa27ce4SDimitry Andric   PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
4715344a3780SDimitry Andric #include "clang/Driver/Options.inc"
4716344a3780SDimitry Andric #undef PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING
4717344a3780SDimitry Andric 
4718344a3780SDimitry Andric   Opts.ShowCPP = isStrictlyPreprocessorAction(Action) && !Args.hasArg(OPT_dM);
47193d1dcd9bSDimitry Andric   Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD);
4720145449b1SDimitry Andric   Opts.DirectivesOnly = Args.hasArg(OPT_fdirectives_only);
4721344a3780SDimitry Andric 
4722344a3780SDimitry Andric   return Diags.getNumErrors() == NumErrorsBefore;
47231569ce68SRoman Divacky }
47241569ce68SRoman Divacky 
GenerateTargetArgs(const TargetOptions & Opts,ArgumentConsumer Consumer)4725344a3780SDimitry Andric static void GenerateTargetArgs(const TargetOptions &Opts,
4726b1c73532SDimitry Andric                                ArgumentConsumer Consumer) {
4727344a3780SDimitry Andric   const TargetOptions *TargetOpts = &Opts;
47287fa27ce4SDimitry Andric #define TARGET_OPTION_WITH_MARSHALLING(...)                                    \
4729b1c73532SDimitry Andric   GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)
4730344a3780SDimitry Andric #include "clang/Driver/Options.inc"
4731344a3780SDimitry Andric #undef TARGET_OPTION_WITH_MARSHALLING
4732344a3780SDimitry Andric 
4733344a3780SDimitry Andric   if (!Opts.SDKVersion.empty())
4734b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_target_sdk_version_EQ,
4735b1c73532SDimitry Andric                 Opts.SDKVersion.getAsString());
4736145449b1SDimitry Andric   if (!Opts.DarwinTargetVariantSDKVersion.empty())
4737b1c73532SDimitry Andric     GenerateArg(Consumer, OPT_darwin_target_variant_sdk_version_EQ,
4738b1c73532SDimitry Andric                 Opts.DarwinTargetVariantSDKVersion.getAsString());
4739344a3780SDimitry Andric }
4740344a3780SDimitry Andric 
ParseTargetArgs(TargetOptions & Opts,ArgList & Args,DiagnosticsEngine & Diags)4741344a3780SDimitry Andric static bool ParseTargetArgs(TargetOptions &Opts, ArgList &Args,
47422b6b257fSDimitry Andric                             DiagnosticsEngine &Diags) {
4743344a3780SDimitry Andric   unsigned NumErrorsBefore = Diags.getNumErrors();
4744344a3780SDimitry Andric 
4745344a3780SDimitry Andric   TargetOptions *TargetOpts = &Opts;
4746344a3780SDimitry Andric 
47477fa27ce4SDimitry Andric #define TARGET_OPTION_WITH_MARSHALLING(...)                                    \
47487fa27ce4SDimitry Andric   PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)
4749344a3780SDimitry Andric #include "clang/Driver/Options.inc"
4750344a3780SDimitry Andric #undef TARGET_OPTION_WITH_MARSHALLING
4751344a3780SDimitry Andric 
4752676fbe81SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_target_sdk_version_EQ)) {
4753676fbe81SDimitry Andric     llvm::VersionTuple Version;
4754676fbe81SDimitry Andric     if (Version.tryParse(A->getValue()))
4755676fbe81SDimitry Andric       Diags.Report(diag::err_drv_invalid_value)
4756676fbe81SDimitry Andric           << A->getAsString(Args) << A->getValue();
4757676fbe81SDimitry Andric     else
4758676fbe81SDimitry Andric       Opts.SDKVersion = Version;
4759676fbe81SDimitry Andric   }
4760145449b1SDimitry Andric   if (Arg *A =
4761145449b1SDimitry Andric           Args.getLastArg(options::OPT_darwin_target_variant_sdk_version_EQ)) {
4762145449b1SDimitry Andric     llvm::VersionTuple Version;
4763145449b1SDimitry Andric     if (Version.tryParse(A->getValue()))
4764145449b1SDimitry Andric       Diags.Report(diag::err_drv_invalid_value)
4765145449b1SDimitry Andric           << A->getAsString(Args) << A->getValue();
4766145449b1SDimitry Andric     else
4767145449b1SDimitry Andric       Opts.DarwinTargetVariantSDKVersion = Version;
4768145449b1SDimitry Andric   }
4769344a3780SDimitry Andric 
4770344a3780SDimitry Andric   return Diags.getNumErrors() == NumErrorsBefore;
47711569ce68SRoman Divacky }
47721569ce68SRoman Divacky 
CreateFromArgsImpl(CompilerInvocation & Res,ArrayRef<const char * > CommandLineArgs,DiagnosticsEngine & Diags,const char * Argv0)4773344a3780SDimitry Andric bool CompilerInvocation::CreateFromArgsImpl(
4774344a3780SDimitry Andric     CompilerInvocation &Res, ArrayRef<const char *> CommandLineArgs,
4775344a3780SDimitry Andric     DiagnosticsEngine &Diags, const char *Argv0) {
4776344a3780SDimitry Andric   unsigned NumErrorsBefore = Diags.getNumErrors();
4777dbe13110SDimitry Andric 
47781569ce68SRoman Divacky   // Parse the arguments.
4779519fc96cSDimitry Andric   const OptTable &Opts = getDriverOptTable();
4780b1c73532SDimitry Andric   llvm::opt::Visibility VisibilityMask(options::CC1Option);
47811569ce68SRoman Divacky   unsigned MissingArgIndex, MissingArgCount;
4782519fc96cSDimitry Andric   InputArgList Args = Opts.ParseArgs(CommandLineArgs, MissingArgIndex,
4783b1c73532SDimitry Andric                                      MissingArgCount, VisibilityMask);
4784b1c73532SDimitry Andric   LangOptions &LangOpts = Res.getLangOpts();
47851569ce68SRoman Divacky 
47861569ce68SRoman Divacky   // Check for missing argument error.
4787344a3780SDimitry Andric   if (MissingArgCount)
47881569ce68SRoman Divacky     Diags.Report(diag::err_drv_missing_argument)
4789c192b3dcSDimitry Andric         << Args.getArgString(MissingArgIndex) << MissingArgCount;
47901569ce68SRoman Divacky 
47911569ce68SRoman Divacky   // Issue errors on unknown arguments.
479248675466SDimitry Andric   for (const auto *A : Args.filtered(OPT_UNKNOWN)) {
479348675466SDimitry Andric     auto ArgString = A->getAsString(Args);
479448675466SDimitry Andric     std::string Nearest;
4795b1c73532SDimitry Andric     if (Opts.findNearest(ArgString, Nearest, VisibilityMask) > 1)
479648675466SDimitry Andric       Diags.Report(diag::err_drv_unknown_argument) << ArgString;
479748675466SDimitry Andric     else
479848675466SDimitry Andric       Diags.Report(diag::err_drv_unknown_argument_with_suggestion)
479948675466SDimitry Andric           << ArgString << Nearest;
4800dbe13110SDimitry Andric   }
48011569ce68SRoman Divacky 
4802344a3780SDimitry Andric   ParseFileSystemArgs(Res.getFileSystemOpts(), Args, Diags);
4803344a3780SDimitry Andric   ParseMigratorArgs(Res.getMigratorOpts(), Args, Diags);
4804b1c73532SDimitry Andric   ParseAnalyzerArgs(Res.getAnalyzerOpts(), Args, Diags);
4805344a3780SDimitry Andric   ParseDiagnosticArgs(Res.getDiagnosticOpts(), Args, &Diags,
4806cfca06d7SDimitry Andric                       /*DefaultDiagColor=*/false);
4807344a3780SDimitry Andric   ParseFrontendArgs(Res.getFrontendOpts(), Args, Diags, LangOpts.IsHeaderFile);
4808bca07a45SDimitry Andric   // FIXME: We shouldn't have to pass the DashX option around here
4809344a3780SDimitry Andric   InputKind DashX = Res.getFrontendOpts().DashX;
48102b6b257fSDimitry Andric   ParseTargetArgs(Res.getTargetOpts(), Args, Diags);
4811b60736ecSDimitry Andric   llvm::Triple T(Res.getTargetOpts().Triple);
4812344a3780SDimitry Andric   ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args, Diags,
48137442d6faSDimitry Andric                         Res.getFileSystemOpts().WorkingDir);
4814b1c73532SDimitry Andric   ParseAPINotesArgs(Res.getAPINotesOpts(), Args, Diags);
4815344a3780SDimitry Andric 
4816ac9a064cSDimitry Andric   ParsePointerAuthArgs(LangOpts, Args, Diags);
4817ac9a064cSDimitry Andric 
4818b60736ecSDimitry Andric   ParseLangArgs(LangOpts, Args, DashX, T, Res.getPreprocessorOpts().Includes,
4819b60736ecSDimitry Andric                 Diags);
4820c3b054d2SDimitry Andric   if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC)
48212b6b257fSDimitry Andric     LangOpts.ObjCExceptions = 1;
48222b6b257fSDimitry Andric 
4823145449b1SDimitry Andric   for (auto Warning : Res.getDiagnosticOpts().Warnings) {
4824145449b1SDimitry Andric     if (Warning == "misexpect" &&
4825145449b1SDimitry Andric         !Diags.isIgnored(diag::warn_profile_data_misexpect, SourceLocation())) {
4826145449b1SDimitry Andric       Res.getCodeGenOpts().MisExpect = true;
4827145449b1SDimitry Andric     }
4828145449b1SDimitry Andric   }
4829145449b1SDimitry Andric 
48302b6b257fSDimitry Andric   if (LangOpts.CUDA) {
48312b6b257fSDimitry Andric     // During CUDA device-side compilation, the aux triple is the
48322b6b257fSDimitry Andric     // triple used for host compilation.
48332b6b257fSDimitry Andric     if (LangOpts.CUDAIsDevice)
48342b6b257fSDimitry Andric       Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple;
48352b6b257fSDimitry Andric   }
48362b6b257fSDimitry Andric 
4837cf1b4019SDimitry Andric   // Set the triple of the host for OpenMP device compile.
48387fa27ce4SDimitry Andric   if (LangOpts.OpenMPIsTargetDevice)
4839cf1b4019SDimitry Andric     Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple;
4840cf1b4019SDimitry Andric 
4841344a3780SDimitry Andric   ParseCodeGenArgs(Res.getCodeGenOpts(), Args, DashX, Diags, T,
4842b60736ecSDimitry Andric                    Res.getFrontendOpts().OutputFile, LangOpts);
4843b60736ecSDimitry Andric 
48442b6b257fSDimitry Andric   // FIXME: Override value name discarding when asan or msan is used because the
48452b6b257fSDimitry Andric   // backend passes depend on the name of the alloca in order to print out
48462b6b257fSDimitry Andric   // names.
48472b6b257fSDimitry Andric   Res.getCodeGenOpts().DiscardValueNames &=
48482b6b257fSDimitry Andric       !LangOpts.Sanitize.has(SanitizerKind::Address) &&
4849676fbe81SDimitry Andric       !LangOpts.Sanitize.has(SanitizerKind::KernelAddress) &&
4850676fbe81SDimitry Andric       !LangOpts.Sanitize.has(SanitizerKind::Memory) &&
4851676fbe81SDimitry Andric       !LangOpts.Sanitize.has(SanitizerKind::KernelMemory);
48522b6b257fSDimitry Andric 
485348675466SDimitry Andric   ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, Diags,
4854344a3780SDimitry Andric                         Res.getFrontendOpts().ProgramAction,
4855344a3780SDimitry Andric                         Res.getFrontendOpts());
4856344a3780SDimitry Andric   ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), Args, Diags,
4857809500fcSDimitry Andric                               Res.getFrontendOpts().ProgramAction);
4858bab175ecSDimitry Andric 
4859344a3780SDimitry Andric   ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), Args, Diags,
4860344a3780SDimitry Andric                             Res.getFrontendOpts().ProgramAction,
4861344a3780SDimitry Andric                             Res.getPreprocessorOutputOpts().ShowLineMarkers);
4862344a3780SDimitry Andric   if (!Res.getDependencyOutputOpts().OutputFile.empty() &&
4863344a3780SDimitry Andric       Res.getDependencyOutputOpts().Targets.empty())
4864344a3780SDimitry Andric     Diags.Report(diag::err_fe_dependency_file_requires_MT);
4865461a67faSDimitry Andric 
4866461a67faSDimitry Andric   // If sanitizer is enabled, disable OPT_ffine_grained_bitfield_accesses.
4867461a67faSDimitry Andric   if (Res.getCodeGenOpts().FineGrainedBitfieldAccesses &&
4868b1c73532SDimitry Andric       !Res.getLangOpts().Sanitize.empty()) {
4869461a67faSDimitry Andric     Res.getCodeGenOpts().FineGrainedBitfieldAccesses = false;
4870461a67faSDimitry Andric     Diags.Report(diag::warn_drv_fine_grained_bitfield_accesses_ignored);
4871461a67faSDimitry Andric   }
4872cfca06d7SDimitry Andric 
4873cfca06d7SDimitry Andric   // Store the command-line for using in the CodeView backend.
4874e3b55780SDimitry Andric   if (Res.getCodeGenOpts().CodeViewCommandLine) {
4875cfca06d7SDimitry Andric     Res.getCodeGenOpts().Argv0 = Argv0;
487677fc4c14SDimitry Andric     append_range(Res.getCodeGenOpts().CommandLineArgs, CommandLineArgs);
4877e3b55780SDimitry Andric   }
4878cfca06d7SDimitry Andric 
48797fa27ce4SDimitry Andric   // Set PGOOptions. Need to create a temporary VFS to read the profile
48807fa27ce4SDimitry Andric   // to determine the PGO type.
48817fa27ce4SDimitry Andric   if (!Res.getCodeGenOpts().ProfileInstrumentUsePath.empty()) {
48827fa27ce4SDimitry Andric     auto FS =
48837fa27ce4SDimitry Andric         createVFSFromOverlayFiles(Res.getHeaderSearchOpts().VFSOverlayFiles,
48847fa27ce4SDimitry Andric                                   Diags, llvm::vfs::getRealFileSystem());
48857fa27ce4SDimitry Andric     setPGOUseInstrumentor(Res.getCodeGenOpts(),
48867fa27ce4SDimitry Andric                           Res.getCodeGenOpts().ProfileInstrumentUsePath, *FS,
48877fa27ce4SDimitry Andric                           Diags);
48887fa27ce4SDimitry Andric   }
48897fa27ce4SDimitry Andric 
4890b60736ecSDimitry Andric   FixupInvocation(Res, Diags, Args, DashX);
4891b60736ecSDimitry Andric 
4892344a3780SDimitry Andric   return Diags.getNumErrors() == NumErrorsBefore;
4893344a3780SDimitry Andric }
4894344a3780SDimitry Andric 
CreateFromArgs(CompilerInvocation & Invocation,ArrayRef<const char * > CommandLineArgs,DiagnosticsEngine & Diags,const char * Argv0)4895344a3780SDimitry Andric bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Invocation,
4896344a3780SDimitry Andric                                         ArrayRef<const char *> CommandLineArgs,
4897344a3780SDimitry Andric                                         DiagnosticsEngine &Diags,
4898344a3780SDimitry Andric                                         const char *Argv0) {
4899344a3780SDimitry Andric   CompilerInvocation DummyInvocation;
4900344a3780SDimitry Andric 
4901344a3780SDimitry Andric   return RoundTrip(
4902344a3780SDimitry Andric       [](CompilerInvocation &Invocation, ArrayRef<const char *> CommandLineArgs,
4903344a3780SDimitry Andric          DiagnosticsEngine &Diags, const char *Argv0) {
4904344a3780SDimitry Andric         return CreateFromArgsImpl(Invocation, CommandLineArgs, Diags, Argv0);
4905344a3780SDimitry Andric       },
4906344a3780SDimitry Andric       [](CompilerInvocation &Invocation, SmallVectorImpl<const char *> &Args,
4907e3b55780SDimitry Andric          StringAllocator SA) {
4908e3b55780SDimitry Andric         Args.push_back("-cc1");
4909e3b55780SDimitry Andric         Invocation.generateCC1CommandLine(Args, SA);
4910e3b55780SDimitry Andric       },
4911344a3780SDimitry Andric       Invocation, DummyInvocation, CommandLineArgs, Diags, Argv0);
49121569ce68SRoman Divacky }
491336981b17SDimitry Andric 
getModuleHash() const491436981b17SDimitry Andric std::string CompilerInvocation::getModuleHash() const {
4915c0981da4SDimitry Andric   // FIXME: Consider using SHA1 instead of MD5.
4916b1c73532SDimitry Andric   llvm::HashBuilder<llvm::MD5, llvm::endianness::native> HBuilder;
4917c0981da4SDimitry Andric 
4918809500fcSDimitry Andric   // Note: For QoI reasons, the things we use as a hash here should all be
4919809500fcSDimitry Andric   // dumped via the -module-info flag.
492036981b17SDimitry Andric 
492136981b17SDimitry Andric   // Start the signature with the compiler version.
4922c0981da4SDimitry Andric   HBuilder.add(getClangFullRepositoryVersion());
492336981b17SDimitry Andric 
4924cfca06d7SDimitry Andric   // Also include the serialization version, in case LLVM_APPEND_VC_REV is off
4925cfca06d7SDimitry Andric   // and getClangFullRepositoryVersion() doesn't include git revision.
4926c0981da4SDimitry Andric   HBuilder.add(serialization::VERSION_MAJOR, serialization::VERSION_MINOR);
4927cfca06d7SDimitry Andric 
492836981b17SDimitry Andric   // Extend the signature with the language options
4929c0981da4SDimitry Andric #define LANGOPT(Name, Bits, Default, Description) HBuilder.add(LangOpts->Name);
493036981b17SDimitry Andric #define ENUM_LANGOPT(Name, Type, Bits, Default, Description)                   \
4931c0981da4SDimitry Andric   HBuilder.add(static_cast<unsigned>(LangOpts->get##Name()));
493236981b17SDimitry Andric #define BENIGN_LANGOPT(Name, Bits, Default, Description)
493336981b17SDimitry Andric #define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)
493436981b17SDimitry Andric #include "clang/Basic/LangOptions.def"
493536981b17SDimitry Andric 
4936b1c73532SDimitry Andric   HBuilder.addRange(getLangOpts().ModuleFeatures);
4937c192b3dcSDimitry Andric 
4938b1c73532SDimitry Andric   HBuilder.add(getLangOpts().ObjCRuntime);
4939b1c73532SDimitry Andric   HBuilder.addRange(getLangOpts().CommentOpts.BlockCommandNames);
4940cfca06d7SDimitry Andric 
494113cc256eSDimitry Andric   // Extend the signature with the target options.
4942b1c73532SDimitry Andric   HBuilder.add(getTargetOpts().Triple, getTargetOpts().CPU,
4943b1c73532SDimitry Andric                getTargetOpts().TuneCPU, getTargetOpts().ABI);
4944b1c73532SDimitry Andric   HBuilder.addRange(getTargetOpts().FeaturesAsWritten);
494536981b17SDimitry Andric 
494636981b17SDimitry Andric   // Extend the signature with preprocessor options.
494713cc256eSDimitry Andric   const PreprocessorOptions &ppOpts = getPreprocessorOpts();
4948c0981da4SDimitry Andric   HBuilder.add(ppOpts.UsePredefines, ppOpts.DetailedRecord);
494936981b17SDimitry Andric 
4950c0981da4SDimitry Andric   const HeaderSearchOptions &hsOpts = getHeaderSearchOpts();
4951c0981da4SDimitry Andric   for (const auto &Macro : getPreprocessorOpts().Macros) {
4952809500fcSDimitry Andric     // If we're supposed to ignore this macro for the purposes of modules,
4953809500fcSDimitry Andric     // don't put it into the hash.
4954809500fcSDimitry Andric     if (!hsOpts.ModulesIgnoreMacros.empty()) {
4955809500fcSDimitry Andric       // Check whether we're ignoring this macro.
4956c0981da4SDimitry Andric       StringRef MacroDef = Macro.first;
4957bab175ecSDimitry Andric       if (hsOpts.ModulesIgnoreMacros.count(
4958bab175ecSDimitry Andric               llvm::CachedHashString(MacroDef.split('=').first)))
4959809500fcSDimitry Andric         continue;
4960809500fcSDimitry Andric     }
4961809500fcSDimitry Andric 
4962c0981da4SDimitry Andric     HBuilder.add(Macro);
496336981b17SDimitry Andric   }
496436981b17SDimitry Andric 
49650414e226SDimitry Andric   // Extend the signature with the sysroot and other header search options.
4966c0981da4SDimitry Andric   HBuilder.add(hsOpts.Sysroot, hsOpts.ModuleFormat, hsOpts.UseDebugInfo,
4967c0981da4SDimitry Andric                hsOpts.UseBuiltinIncludes, hsOpts.UseStandardSystemIncludes,
4968c0981da4SDimitry Andric                hsOpts.UseStandardCXXIncludes, hsOpts.UseLibcxx,
4969bab175ecSDimitry Andric                hsOpts.ModulesValidateDiagnosticOptions);
4970c0981da4SDimitry Andric   HBuilder.add(hsOpts.ResourceDir);
49719f4dbff6SDimitry Andric 
4972519fc96cSDimitry Andric   if (hsOpts.ModulesStrictContextHash) {
4973c0981da4SDimitry Andric     HBuilder.addRange(hsOpts.SystemHeaderPrefixes);
4974c0981da4SDimitry Andric     HBuilder.addRange(hsOpts.UserEntries);
4975ac9a064cSDimitry Andric     HBuilder.addRange(hsOpts.VFSOverlayFiles);
4976519fc96cSDimitry Andric 
4977519fc96cSDimitry Andric     const DiagnosticOptions &diagOpts = getDiagnosticOpts();
4978c0981da4SDimitry Andric #define DIAGOPT(Name, Bits, Default) HBuilder.add(diagOpts.Name);
4979519fc96cSDimitry Andric #define ENUM_DIAGOPT(Name, Type, Bits, Default)                                \
4980c0981da4SDimitry Andric   HBuilder.add(diagOpts.get##Name());
4981519fc96cSDimitry Andric #include "clang/Basic/DiagnosticOptions.def"
4982519fc96cSDimitry Andric #undef DIAGOPT
4983519fc96cSDimitry Andric #undef ENUM_DIAGOPT
4984519fc96cSDimitry Andric   }
4985519fc96cSDimitry Andric 
49869f4dbff6SDimitry Andric   // Extend the signature with the user build path.
4987c0981da4SDimitry Andric   HBuilder.add(hsOpts.ModuleUserBuildPath);
498836981b17SDimitry Andric 
498945b53394SDimitry Andric   // Extend the signature with the module file extensions.
4990c0981da4SDimitry Andric   for (const auto &ext : getFrontendOpts().ModuleFileExtensions)
4991c0981da4SDimitry Andric     ext->hashExtension(HBuilder);
499245b53394SDimitry Andric 
4993b1c73532SDimitry Andric   // Extend the signature with the Swift version for API notes.
4994b1c73532SDimitry Andric   const APINotesOptions &APINotesOpts = getAPINotesOpts();
4995b1c73532SDimitry Andric   if (!APINotesOpts.SwiftVersion.empty()) {
4996b1c73532SDimitry Andric     HBuilder.add(APINotesOpts.SwiftVersion.getMajor());
4997b1c73532SDimitry Andric     if (auto Minor = APINotesOpts.SwiftVersion.getMinor())
4998b1c73532SDimitry Andric       HBuilder.add(*Minor);
4999b1c73532SDimitry Andric     if (auto Subminor = APINotesOpts.SwiftVersion.getSubminor())
5000b1c73532SDimitry Andric       HBuilder.add(*Subminor);
5001b1c73532SDimitry Andric     if (auto Build = APINotesOpts.SwiftVersion.getBuild())
5002b1c73532SDimitry Andric       HBuilder.add(*Build);
5003b1c73532SDimitry Andric   }
5004b1c73532SDimitry Andric 
5005676fbe81SDimitry Andric   // When compiling with -gmodules, also hash -fdebug-prefix-map as it
5006676fbe81SDimitry Andric   // affects the debug info in the PCM.
5007676fbe81SDimitry Andric   if (getCodeGenOpts().DebugTypeExtRefs)
5008c0981da4SDimitry Andric     HBuilder.addRange(getCodeGenOpts().DebugPrefixMap);
5009676fbe81SDimitry Andric 
5010b1c73532SDimitry Andric   // Extend the signature with the affecting debug options.
5011b1c73532SDimitry Andric   if (getHeaderSearchOpts().ModuleFormat == "obj") {
5012b1c73532SDimitry Andric #define DEBUGOPT(Name, Bits, Default) HBuilder.add(CodeGenOpts->Name);
5013b1c73532SDimitry Andric #define VALUE_DEBUGOPT(Name, Bits, Default) HBuilder.add(CodeGenOpts->Name);
5014b1c73532SDimitry Andric #define ENUM_DEBUGOPT(Name, Type, Bits, Default)                               \
5015b1c73532SDimitry Andric   HBuilder.add(static_cast<unsigned>(CodeGenOpts->get##Name()));
5016b1c73532SDimitry Andric #define BENIGN_DEBUGOPT(Name, Bits, Default)
5017b1c73532SDimitry Andric #define BENIGN_VALUE_DEBUGOPT(Name, Bits, Default)
5018b1c73532SDimitry Andric #define BENIGN_ENUM_DEBUGOPT(Name, Type, Bits, Default)
5019b1c73532SDimitry Andric #include "clang/Basic/DebugOptions.def"
5020b1c73532SDimitry Andric   }
5021b1c73532SDimitry Andric 
5022551c6985SDimitry Andric   // Extend the signature with the enabled sanitizers, if at least one is
5023551c6985SDimitry Andric   // enabled. Sanitizers which cannot affect AST generation aren't hashed.
5024b1c73532SDimitry Andric   SanitizerSet SanHash = getLangOpts().Sanitize;
5025551c6985SDimitry Andric   SanHash.clear(getPPTransparentSanitizers());
5026551c6985SDimitry Andric   if (!SanHash.empty())
5027c0981da4SDimitry Andric     HBuilder.add(SanHash.Mask);
5028551c6985SDimitry Andric 
5029c0981da4SDimitry Andric   llvm::MD5::MD5Result Result;
5030c0981da4SDimitry Andric   HBuilder.getHasher().final(Result);
5031c0981da4SDimitry Andric   uint64_t Hash = Result.high() ^ Result.low();
5032c0981da4SDimitry Andric   return toString(llvm::APInt(64, Hash), 36, /*Signed=*/false);
503336981b17SDimitry Andric }
5034bfef3995SDimitry Andric 
generateCC1CommandLine(ArgumentConsumer Consumer) const5035b1c73532SDimitry Andric void CompilerInvocationBase::generateCC1CommandLine(
5036b1c73532SDimitry Andric     ArgumentConsumer Consumer) const {
5037b1c73532SDimitry Andric   llvm::Triple T(getTargetOpts().Triple);
5038cfca06d7SDimitry Andric 
5039b1c73532SDimitry Andric   GenerateFileSystemArgs(getFileSystemOpts(), Consumer);
5040b1c73532SDimitry Andric   GenerateMigratorArgs(getMigratorOpts(), Consumer);
5041b1c73532SDimitry Andric   GenerateAnalyzerArgs(getAnalyzerOpts(), Consumer);
5042b1c73532SDimitry Andric   GenerateDiagnosticArgs(getDiagnosticOpts(), Consumer,
5043b1c73532SDimitry Andric                          /*DefaultDiagColor=*/false);
5044b1c73532SDimitry Andric   GenerateFrontendArgs(getFrontendOpts(), Consumer, getLangOpts().IsHeaderFile);
5045b1c73532SDimitry Andric   GenerateTargetArgs(getTargetOpts(), Consumer);
5046b1c73532SDimitry Andric   GenerateHeaderSearchArgs(getHeaderSearchOpts(), Consumer);
5047b1c73532SDimitry Andric   GenerateAPINotesArgs(getAPINotesOpts(), Consumer);
5048ac9a064cSDimitry Andric   GeneratePointerAuthArgs(getLangOpts(), Consumer);
5049b1c73532SDimitry Andric   GenerateLangArgs(getLangOpts(), Consumer, T, getFrontendOpts().DashX);
5050b1c73532SDimitry Andric   GenerateCodeGenArgs(getCodeGenOpts(), Consumer, T,
5051b1c73532SDimitry Andric                       getFrontendOpts().OutputFile, &getLangOpts());
5052b1c73532SDimitry Andric   GeneratePreprocessorArgs(getPreprocessorOpts(), Consumer, getLangOpts(),
5053b1c73532SDimitry Andric                            getFrontendOpts(), getCodeGenOpts());
5054b1c73532SDimitry Andric   GeneratePreprocessorOutputArgs(getPreprocessorOutputOpts(), Consumer,
5055b1c73532SDimitry Andric                                  getFrontendOpts().ProgramAction);
5056b1c73532SDimitry Andric   GenerateDependencyOutputArgs(getDependencyOutputOpts(), Consumer);
5057cfca06d7SDimitry Andric }
5058cfca06d7SDimitry Andric 
getCC1CommandLine() const5059b1c73532SDimitry Andric std::vector<std::string> CompilerInvocationBase::getCC1CommandLine() const {
5060b1c73532SDimitry Andric   std::vector<std::string> Args{"-cc1"};
5061b1c73532SDimitry Andric   generateCC1CommandLine(
5062b1c73532SDimitry Andric       [&Args](const Twine &Arg) { Args.push_back(Arg.str()); });
5063b1c73532SDimitry Andric   return Args;
5064e3b55780SDimitry Andric }
5065e3b55780SDimitry Andric 
resetNonModularOptions()5066e3b55780SDimitry Andric void CompilerInvocation::resetNonModularOptions() {
5067b1c73532SDimitry Andric   getLangOpts().resetNonModularOptions();
5068e3b55780SDimitry Andric   getPreprocessorOpts().resetNonModularOptions();
5069b1c73532SDimitry Andric   getCodeGenOpts().resetNonModularOptions(getHeaderSearchOpts().ModuleFormat);
5070e3b55780SDimitry Andric }
5071e3b55780SDimitry Andric 
clearImplicitModuleBuildOptions()5072e3b55780SDimitry Andric void CompilerInvocation::clearImplicitModuleBuildOptions() {
5073b1c73532SDimitry Andric   getLangOpts().ImplicitModules = false;
5074e3b55780SDimitry Andric   getHeaderSearchOpts().ImplicitModuleMaps = false;
5075e3b55780SDimitry Andric   getHeaderSearchOpts().ModuleCachePath.clear();
5076e3b55780SDimitry Andric   getHeaderSearchOpts().ModulesValidateOncePerBuildSession = false;
5077e3b55780SDimitry Andric   getHeaderSearchOpts().BuildSessionTimestamp = 0;
5078e3b55780SDimitry Andric   // The specific values we canonicalize to for pruning don't affect behaviour,
5079e3b55780SDimitry Andric   /// so use the default values so they may be dropped from the command-line.
5080e3b55780SDimitry Andric   getHeaderSearchOpts().ModuleCachePruneInterval = 7 * 24 * 60 * 60;
5081e3b55780SDimitry Andric   getHeaderSearchOpts().ModuleCachePruneAfter = 31 * 24 * 60 * 60;
5082e3b55780SDimitry Andric }
5083e3b55780SDimitry Andric 
5084676fbe81SDimitry Andric IntrusiveRefCntPtr<llvm::vfs::FileSystem>
createVFSFromCompilerInvocation(const CompilerInvocation & CI,DiagnosticsEngine & Diags)5085b60736ecSDimitry Andric clang::createVFSFromCompilerInvocation(const CompilerInvocation &CI,
50869f4dbff6SDimitry Andric                                        DiagnosticsEngine &Diags) {
5087676fbe81SDimitry Andric   return createVFSFromCompilerInvocation(CI, Diags,
5088676fbe81SDimitry Andric                                          llvm::vfs::getRealFileSystem());
5089b5aee35cSDimitry Andric }
50909f4dbff6SDimitry Andric 
5091b60736ecSDimitry Andric IntrusiveRefCntPtr<llvm::vfs::FileSystem>
createVFSFromCompilerInvocation(const CompilerInvocation & CI,DiagnosticsEngine & Diags,IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS)5092b60736ecSDimitry Andric clang::createVFSFromCompilerInvocation(
5093676fbe81SDimitry Andric     const CompilerInvocation &CI, DiagnosticsEngine &Diags,
5094676fbe81SDimitry Andric     IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS) {
5095e3b55780SDimitry Andric   return createVFSFromOverlayFiles(CI.getHeaderSearchOpts().VFSOverlayFiles,
5096e3b55780SDimitry Andric                                    Diags, std::move(BaseFS));
5097e3b55780SDimitry Andric }
5098e3b55780SDimitry Andric 
createVFSFromOverlayFiles(ArrayRef<std::string> VFSOverlayFiles,DiagnosticsEngine & Diags,IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS)5099e3b55780SDimitry Andric IntrusiveRefCntPtr<llvm::vfs::FileSystem> clang::createVFSFromOverlayFiles(
5100e3b55780SDimitry Andric     ArrayRef<std::string> VFSOverlayFiles, DiagnosticsEngine &Diags,
5101e3b55780SDimitry Andric     IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS) {
5102e3b55780SDimitry Andric   if (VFSOverlayFiles.empty())
5103b5aee35cSDimitry Andric     return BaseFS;
5104b5aee35cSDimitry Andric 
5105676fbe81SDimitry Andric   IntrusiveRefCntPtr<llvm::vfs::FileSystem> Result = BaseFS;
51069f4dbff6SDimitry Andric   // earlier vfs files are on the bottom
5107e3b55780SDimitry Andric   for (const auto &File : VFSOverlayFiles) {
51089f4dbff6SDimitry Andric     llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =
5109676fbe81SDimitry Andric         Result->getBufferForFile(File);
51109f4dbff6SDimitry Andric     if (!Buffer) {
51119f4dbff6SDimitry Andric       Diags.Report(diag::err_missing_vfs_overlay_file) << File;
511248675466SDimitry Andric       continue;
51139f4dbff6SDimitry Andric     }
51149f4dbff6SDimitry Andric 
5115676fbe81SDimitry Andric     IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = llvm::vfs::getVFSFromYAML(
5116676fbe81SDimitry Andric         std::move(Buffer.get()), /*DiagHandler*/ nullptr, File,
5117676fbe81SDimitry Andric         /*DiagContext*/ nullptr, Result);
5118676fbe81SDimitry Andric     if (!FS) {
511948675466SDimitry Andric       Diags.Report(diag::err_invalid_vfs_overlay) << File;
5120676fbe81SDimitry Andric       continue;
51219f4dbff6SDimitry Andric     }
5122676fbe81SDimitry Andric 
5123676fbe81SDimitry Andric     Result = FS;
5124676fbe81SDimitry Andric   }
5125676fbe81SDimitry Andric   return Result;
51269f4dbff6SDimitry Andric }
5127