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