2018-03-27 05:45:04 +08:00
|
|
|
//===- CompilerInvocation.cpp ---------------------------------------------===//
|
2009-11-17 14:02:29 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2009-11-17 14:02:29 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2016-07-19 03:02:11 +08:00
|
|
|
#include "clang/Frontend/CompilerInvocation.h"
|
2015-11-04 02:33:07 +08:00
|
|
|
#include "TestModuleFileExtension.h"
|
2016-01-06 22:35:46 +08:00
|
|
|
#include "clang/Basic/Builtins.h"
|
2018-03-27 05:45:04 +08:00
|
|
|
#include "clang/Basic/CharInfo.h"
|
2018-12-11 11:18:39 +08:00
|
|
|
#include "clang/Basic/CodeGenOptions.h"
|
2018-03-27 05:45:04 +08:00
|
|
|
#include "clang/Basic/CommentOptions.h"
|
|
|
|
#include "clang/Basic/DebugInfoOptions.h"
|
|
|
|
#include "clang/Basic/Diagnostic.h"
|
|
|
|
#include "clang/Basic/DiagnosticOptions.h"
|
|
|
|
#include "clang/Basic/FileSystemOptions.h"
|
|
|
|
#include "clang/Basic/LLVM.h"
|
|
|
|
#include "clang/Basic/LangOptions.h"
|
2019-08-05 21:59:26 +08:00
|
|
|
#include "clang/Basic/LangStandard.h"
|
2018-03-27 05:45:04 +08:00
|
|
|
#include "clang/Basic/ObjCRuntime.h"
|
|
|
|
#include "clang/Basic/Sanitizers.h"
|
|
|
|
#include "clang/Basic/SourceLocation.h"
|
|
|
|
#include "clang/Basic/TargetOptions.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/Basic/Version.h"
|
2018-03-27 05:45:04 +08:00
|
|
|
#include "clang/Basic/Visibility.h"
|
2018-04-13 10:31:58 +08:00
|
|
|
#include "clang/Basic/XRayInstr.h"
|
2014-12-29 20:09:08 +08:00
|
|
|
#include "clang/Config/config.h"
|
2019-02-01 06:15:32 +08:00
|
|
|
#include "clang/Driver/Driver.h"
|
2009-12-01 11:16:53 +08:00
|
|
|
#include "clang/Driver/DriverDiagnostic.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/Driver/Options.h"
|
2018-03-27 05:45:04 +08:00
|
|
|
#include "clang/Frontend/CommandLineSourceLoc.h"
|
|
|
|
#include "clang/Frontend/DependencyOutputOptions.h"
|
2014-04-16 02:16:25 +08:00
|
|
|
#include "clang/Frontend/FrontendDiagnostic.h"
|
2018-03-27 05:45:04 +08:00
|
|
|
#include "clang/Frontend/FrontendOptions.h"
|
2019-01-04 02:26:06 +08:00
|
|
|
#include "clang/Frontend/FrontendPluginRegistry.h"
|
2018-03-27 05:45:04 +08:00
|
|
|
#include "clang/Frontend/MigratorOptions.h"
|
|
|
|
#include "clang/Frontend/PreprocessorOutputOptions.h"
|
2013-06-15 01:17:23 +08:00
|
|
|
#include "clang/Frontend/Utils.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/Lex/HeaderSearchOptions.h"
|
2016-07-19 03:02:11 +08:00
|
|
|
#include "clang/Lex/PreprocessorOptions.h"
|
2018-03-27 05:45:04 +08:00
|
|
|
#include "clang/Sema/CodeCompleteOptions.h"
|
2015-11-04 02:33:07 +08:00
|
|
|
#include "clang/Serialization/ModuleFileExtension.h"
|
2018-03-27 05:45:04 +08:00
|
|
|
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
|
|
|
|
#include "llvm/ADT/APInt.h"
|
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
|
|
#include "llvm/ADT/CachedHashString.h"
|
2012-11-06 03:45:09 +08:00
|
|
|
#include "llvm/ADT/Hashing.h"
|
2018-03-27 05:45:04 +08:00
|
|
|
#include "llvm/ADT/None.h"
|
|
|
|
#include "llvm/ADT/Optional.h"
|
|
|
|
#include "llvm/ADT/SmallString.h"
|
2015-01-14 19:29:14 +08:00
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2018-03-27 05:45:04 +08:00
|
|
|
#include "llvm/ADT/StringRef.h"
|
2009-12-01 11:16:53 +08:00
|
|
|
#include "llvm/ADT/StringSwitch.h"
|
2010-08-30 17:42:39 +08:00
|
|
|
#include "llvm/ADT/Triple.h"
|
2018-03-27 05:45:04 +08:00
|
|
|
#include "llvm/ADT/Twine.h"
|
2018-08-21 04:14:08 +08:00
|
|
|
#include "llvm/IR/DebugInfoMetadata.h"
|
2015-10-28 01:56:59 +08:00
|
|
|
#include "llvm/Linker/Linker.h"
|
2018-03-27 05:45:04 +08:00
|
|
|
#include "llvm/MC/MCTargetOptions.h"
|
2013-06-15 01:17:23 +08:00
|
|
|
#include "llvm/Option/Arg.h"
|
|
|
|
#include "llvm/Option/ArgList.h"
|
2018-03-27 05:45:04 +08:00
|
|
|
#include "llvm/Option/OptSpecifier.h"
|
2013-06-15 01:17:23 +08:00
|
|
|
#include "llvm/Option/OptTable.h"
|
|
|
|
#include "llvm/Option/Option.h"
|
2016-03-03 04:59:36 +08:00
|
|
|
#include "llvm/ProfileData/InstrProfReader.h"
|
2014-05-08 10:28:32 +08:00
|
|
|
#include "llvm/Support/CodeGen.h"
|
2018-03-27 05:45:04 +08:00
|
|
|
#include "llvm/Support/Compiler.h"
|
|
|
|
#include "llvm/Support/Error.h"
|
2009-11-17 14:02:29 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2018-03-27 05:45:04 +08:00
|
|
|
#include "llvm/Support/ErrorOr.h"
|
2013-06-26 13:03:40 +08:00
|
|
|
#include "llvm/Support/FileSystem.h"
|
2010-11-30 02:12:39 +08:00
|
|
|
#include "llvm/Support/Host.h"
|
2018-03-27 05:45:04 +08:00
|
|
|
#include "llvm/Support/MathExtras.h"
|
|
|
|
#include "llvm/Support/MemoryBuffer.h"
|
2010-11-30 02:12:39 +08:00
|
|
|
#include "llvm/Support/Path.h"
|
2013-09-11 08:38:02 +08:00
|
|
|
#include "llvm/Support/Process.h"
|
2018-03-27 05:45:04 +08:00
|
|
|
#include "llvm/Support/Regex.h"
|
2018-06-11 18:28:04 +08:00
|
|
|
#include "llvm/Support/VersionTuple.h"
|
2018-10-10 21:27:25 +08:00
|
|
|
#include "llvm/Support/VirtualFileSystem.h"
|
2018-03-27 05:45:04 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2015-11-09 20:40:41 +08:00
|
|
|
#include "llvm/Target/TargetOptions.h"
|
2018-03-27 05:45:04 +08:00
|
|
|
#include <algorithm>
|
2014-03-03 01:08:31 +08:00
|
|
|
#include <atomic>
|
2018-03-27 05:45:04 +08:00
|
|
|
#include <cassert>
|
|
|
|
#include <cstddef>
|
|
|
|
#include <cstring>
|
2014-03-09 19:36:40 +08:00
|
|
|
#include <memory>
|
2018-03-27 05:45:04 +08:00
|
|
|
#include <string>
|
|
|
|
#include <tuple>
|
|
|
|
#include <utility>
|
|
|
|
#include <vector>
|
|
|
|
|
2009-11-17 14:02:29 +08:00
|
|
|
using namespace clang;
|
2018-03-27 05:45:04 +08:00
|
|
|
using namespace driver;
|
|
|
|
using namespace options;
|
|
|
|
using namespace llvm::opt;
|
2009-11-17 14:02:29 +08:00
|
|
|
|
2011-11-18 07:01:24 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Initialization.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-11-18 12:32:13 +08:00
|
|
|
CompilerInvocationBase::CompilerInvocationBase()
|
2018-03-27 05:45:04 +08:00
|
|
|
: LangOpts(new LangOptions()), TargetOpts(new TargetOptions()),
|
|
|
|
DiagnosticOpts(new DiagnosticOptions()),
|
|
|
|
HeaderSearchOpts(new HeaderSearchOptions()),
|
|
|
|
PreprocessorOpts(new PreprocessorOptions()) {}
|
2011-11-18 07:01:24 +08:00
|
|
|
|
2011-11-18 12:32:13 +08:00
|
|
|
CompilerInvocationBase::CompilerInvocationBase(const CompilerInvocationBase &X)
|
2017-01-07 03:49:01 +08:00
|
|
|
: LangOpts(new LangOptions(*X.getLangOpts())),
|
|
|
|
TargetOpts(new TargetOptions(X.getTargetOpts())),
|
|
|
|
DiagnosticOpts(new DiagnosticOptions(X.getDiagnosticOpts())),
|
|
|
|
HeaderSearchOpts(new HeaderSearchOptions(X.getHeaderSearchOpts())),
|
|
|
|
PreprocessorOpts(new PreprocessorOptions(X.getPreprocessorOpts())) {}
|
2011-11-18 07:01:24 +08:00
|
|
|
|
2018-03-27 05:45:04 +08:00
|
|
|
CompilerInvocationBase::~CompilerInvocationBase() = default;
|
2014-05-12 06:10:52 +08:00
|
|
|
|
2011-11-18 07:01:24 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2012-11-01 11:48:49 +08:00
|
|
|
// Deserialization (from args)
|
2009-12-01 11:16:53 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2010-12-04 09:50:36 +08:00
|
|
|
static unsigned getOptimizationLevel(ArgList &Args, InputKind IK,
|
2011-09-26 07:23:43 +08:00
|
|
|
DiagnosticsEngine &Diags) {
|
2018-11-27 01:26:49 +08:00
|
|
|
unsigned DefaultOpt = llvm::CodeGenOpt::None;
|
2019-08-05 21:59:26 +08:00
|
|
|
if (IK.getLanguage() == Language::OpenCL && !Args.hasArg(OPT_cl_opt_disable))
|
2018-11-27 01:26:49 +08:00
|
|
|
DefaultOpt = llvm::CodeGenOpt::Default;
|
2012-05-01 22:57:16 +08:00
|
|
|
|
|
|
|
if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
|
|
|
|
if (A->getOption().matches(options::OPT_O0))
|
2018-11-27 01:26:49 +08:00
|
|
|
return llvm::CodeGenOpt::None;
|
2012-05-01 22:57:16 +08:00
|
|
|
|
2013-04-11 05:26:02 +08:00
|
|
|
if (A->getOption().matches(options::OPT_Ofast))
|
2018-11-27 01:26:49 +08:00
|
|
|
return llvm::CodeGenOpt::Aggressive;
|
2013-04-11 05:26:02 +08:00
|
|
|
|
2018-03-27 05:45:04 +08:00
|
|
|
assert(A->getOption().matches(options::OPT_O));
|
2012-05-01 22:57:16 +08:00
|
|
|
|
2013-01-13 03:30:44 +08:00
|
|
|
StringRef S(A->getValue());
|
2012-05-01 22:57:16 +08:00
|
|
|
if (S == "s" || S == "z" || S.empty())
|
2018-11-27 01:26:49 +08:00
|
|
|
return llvm::CodeGenOpt::Default;
|
2012-05-01 22:57:16 +08:00
|
|
|
|
Add a new optimization option -Og
Summary:
Just like gcc, we should have the -Og option as more and more software are using it:
https://llvm.org/bugs/show_bug.cgi?id=20765
Reviewers: echristo, dberlin, dblaikie, keith.walker.arm, rengolin
Subscribers: aprantl, friss, mehdi_amini, RKSimon, probinson, majnemer, cfe-commits
Differential Revision: https://reviews.llvm.org/D24998
llvm-svn: 286602
2016-11-12 01:29:56 +08:00
|
|
|
if (S == "g")
|
2018-11-27 01:26:49 +08:00
|
|
|
return llvm::CodeGenOpt::Less;
|
Add a new optimization option -Og
Summary:
Just like gcc, we should have the -Og option as more and more software are using it:
https://llvm.org/bugs/show_bug.cgi?id=20765
Reviewers: echristo, dberlin, dblaikie, keith.walker.arm, rengolin
Subscribers: aprantl, friss, mehdi_amini, RKSimon, probinson, majnemer, cfe-commits
Differential Revision: https://reviews.llvm.org/D24998
llvm-svn: 286602
2016-11-12 01:29:56 +08:00
|
|
|
|
2013-06-15 01:17:23 +08:00
|
|
|
return getLastArgIntValue(Args, OPT_O, DefaultOpt, Diags);
|
2012-05-01 22:57:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return DefaultOpt;
|
|
|
|
}
|
|
|
|
|
2013-04-11 05:30:03 +08:00
|
|
|
static unsigned getOptimizationLevelSize(ArgList &Args) {
|
2012-05-01 22:57:16 +08:00
|
|
|
if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
|
|
|
|
if (A->getOption().matches(options::OPT_O)) {
|
2012-11-01 12:30:05 +08:00
|
|
|
switch (A->getValue()[0]) {
|
2012-05-01 22:57:16 +08:00
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
case 's':
|
|
|
|
return 1;
|
|
|
|
case 'z':
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Use -Rblah, not -Wblah, to control remark diagnostics. This was always the
intent when we added remark support, but was never implemented in the general
case, because the first -R flags didn't need it. (-Rpass= had special handling
to accomodate its argument.)
-Rno-foo, -Reverything, and -Rno-everything can be used to turn off a remark,
or to turn on or off all remarks. Per discussion on cfe-commits, -Weverything
does not affect remarks, and -Reverything does not affect warnings or errors.
The only "real" -R flag we have right now is -Rmodule-build; that flag is
effectively renamed from -Wmodule-build to -Rmodule-build by this change.
-Wpass and -Wno-pass (and their friends) are also renamed to -Rpass and
-Rno-pass by this change; it's not completely clear whether we intended to have
a -Rpass (with no =pattern), but that is unchanged by this commit, other than
the flag name. The default pattern is effectively one which matches no passes.
In future, we may want to make the default pattern be .*, so that -Reverything
works for -Rpass properly.
llvm-svn: 215046
2014-08-07 08:24:21 +08:00
|
|
|
static void addDiagnosticArgs(ArgList &Args, OptSpecifier Group,
|
|
|
|
OptSpecifier GroupWithValue,
|
|
|
|
std::vector<std::string> &Diagnostics) {
|
2018-03-27 05:45:04 +08:00
|
|
|
for (auto *A : Args.filtered(Group)) {
|
2012-05-01 22:57:16 +08:00
|
|
|
if (A->getOption().getKind() == Option::FlagClass) {
|
Use -Rblah, not -Wblah, to control remark diagnostics. This was always the
intent when we added remark support, but was never implemented in the general
case, because the first -R flags didn't need it. (-Rpass= had special handling
to accomodate its argument.)
-Rno-foo, -Reverything, and -Rno-everything can be used to turn off a remark,
or to turn on or off all remarks. Per discussion on cfe-commits, -Weverything
does not affect remarks, and -Reverything does not affect warnings or errors.
The only "real" -R flag we have right now is -Rmodule-build; that flag is
effectively renamed from -Wmodule-build to -Rmodule-build by this change.
-Wpass and -Wno-pass (and their friends) are also renamed to -Rpass and
-Rno-pass by this change; it's not completely clear whether we intended to have
a -Rpass (with no =pattern), but that is unchanged by this commit, other than
the flag name. The default pattern is effectively one which matches no passes.
In future, we may want to make the default pattern be .*, so that -Reverything
works for -Rpass properly.
llvm-svn: 215046
2014-08-07 08:24:21 +08:00
|
|
|
// The argument is a pure flag (such as OPT_Wall or OPT_Wdeprecated). Add
|
|
|
|
// its name (minus the "W" or "R" at the beginning) to the warning list.
|
|
|
|
Diagnostics.push_back(A->getOption().getName().drop_front(1));
|
|
|
|
} else if (A->getOption().matches(GroupWithValue)) {
|
|
|
|
// This is -Wfoo= or -Rfoo=, where foo is the name of the diagnostic group.
|
|
|
|
Diagnostics.push_back(A->getOption().getName().drop_front(1).rtrim("=-"));
|
2012-05-01 22:57:16 +08:00
|
|
|
} else {
|
Use -Rblah, not -Wblah, to control remark diagnostics. This was always the
intent when we added remark support, but was never implemented in the general
case, because the first -R flags didn't need it. (-Rpass= had special handling
to accomodate its argument.)
-Rno-foo, -Reverything, and -Rno-everything can be used to turn off a remark,
or to turn on or off all remarks. Per discussion on cfe-commits, -Weverything
does not affect remarks, and -Reverything does not affect warnings or errors.
The only "real" -R flag we have right now is -Rmodule-build; that flag is
effectively renamed from -Wmodule-build to -Rmodule-build by this change.
-Wpass and -Wno-pass (and their friends) are also renamed to -Rpass and
-Rno-pass by this change; it's not completely clear whether we intended to have
a -Rpass (with no =pattern), but that is unchanged by this commit, other than
the flag name. The default pattern is effectively one which matches no passes.
In future, we may want to make the default pattern be .*, so that -Reverything
works for -Rpass properly.
llvm-svn: 215046
2014-08-07 08:24:21 +08:00
|
|
|
// Otherwise, add its value (for OPT_W_Joined and similar).
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *Arg : A->getValues())
|
2015-05-30 03:42:19 +08:00
|
|
|
Diagnostics.emplace_back(Arg);
|
2012-05-01 22:57:16 +08:00
|
|
|
}
|
|
|
|
}
|
2010-12-04 09:50:36 +08:00
|
|
|
}
|
|
|
|
|
2018-12-01 05:24:31 +08:00
|
|
|
// Parse the Static Analyzer configuration. If \p Diags is set to nullptr,
|
|
|
|
// it won't verify the input.
|
[analyzer] Evaluate all non-checker config options before analysis
In earlier patches regarding AnalyzerOptions, a lot of effort went into
gathering all config options, and changing the interface so that potential
misuse can be eliminited.
Up until this point, AnalyzerOptions only evaluated an option when it was
querried. For example, if we had a "-no-false-positives" flag, AnalyzerOptions
would store an Optional field for it that would be None up until somewhere in
the code until the flag's getter function is called.
However, now that we're confident that we've gathered all configs, we can
evaluate off of them before analysis, so we can emit a error on invalid input
even if that prticular flag will not matter in that particular run of the
analyzer. Another very big benefit of this is that debug.ConfigDumper will now
show the value of all configs every single time.
Also, almost all options related class have a similar interface, so uniformity
is also a benefit.
The implementation for errors on invalid input will be commited shorty.
Differential Revision: https://reviews.llvm.org/D53692
llvm-svn: 348031
2018-12-01 04:44:00 +08:00
|
|
|
static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts,
|
2018-12-01 05:24:31 +08:00
|
|
|
DiagnosticsEngine *Diags);
|
[analyzer] Evaluate all non-checker config options before analysis
In earlier patches regarding AnalyzerOptions, a lot of effort went into
gathering all config options, and changing the interface so that potential
misuse can be eliminited.
Up until this point, AnalyzerOptions only evaluated an option when it was
querried. For example, if we had a "-no-false-positives" flag, AnalyzerOptions
would store an Optional field for it that would be None up until somewhere in
the code until the flag's getter function is called.
However, now that we're confident that we've gathered all configs, we can
evaluate off of them before analysis, so we can emit a error on invalid input
even if that prticular flag will not matter in that particular run of the
analyzer. Another very big benefit of this is that debug.ConfigDumper will now
show the value of all configs every single time.
Also, almost all options related class have a similar interface, so uniformity
is also a benefit.
The implementation for errors on invalid input will be commited shorty.
Differential Revision: https://reviews.llvm.org/D53692
llvm-svn: 348031
2018-12-01 04:44:00 +08:00
|
|
|
|
2016-01-06 22:35:46 +08:00
|
|
|
static void getAllNoBuiltinFuncValues(ArgList &Args,
|
|
|
|
std::vector<std::string> &Funcs) {
|
|
|
|
SmallVector<const char *, 8> Values;
|
|
|
|
for (const auto &Arg : Args) {
|
|
|
|
const Option &O = Arg->getOption();
|
|
|
|
if (O.matches(options::OPT_fno_builtin_)) {
|
|
|
|
const char *FuncName = Arg->getValue();
|
|
|
|
if (Builtin::Context::isBuiltinFunc(FuncName))
|
|
|
|
Values.push_back(FuncName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Funcs.insert(Funcs.end(), Values.begin(), Values.end());
|
|
|
|
}
|
|
|
|
|
2011-12-23 11:05:38 +08:00
|
|
|
static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
|
2011-09-26 07:23:43 +08:00
|
|
|
DiagnosticsEngine &Diags) {
|
2011-12-23 11:05:38 +08:00
|
|
|
bool Success = true;
|
2009-12-01 11:16:53 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_analyzer_store)) {
|
2012-11-01 12:30:05 +08:00
|
|
|
StringRef Name = A->getValue();
|
2009-12-01 11:16:53 +08:00
|
|
|
AnalysisStores Value = llvm::StringSwitch<AnalysisStores>(Name)
|
|
|
|
#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) \
|
|
|
|
.Case(CMDFLAG, NAME##Model)
|
2012-08-31 12:35:58 +08:00
|
|
|
#include "clang/StaticAnalyzer/Core/Analyses.def"
|
2009-12-01 11:16:53 +08:00
|
|
|
.Default(NumStores);
|
2011-12-23 11:05:38 +08:00
|
|
|
if (Value == NumStores) {
|
2009-12-01 11:16:53 +08:00
|
|
|
Diags.Report(diag::err_drv_invalid_value)
|
2010-06-10 06:30:54 +08:00
|
|
|
<< A->getAsString(Args) << Name;
|
2011-12-23 11:05:38 +08:00
|
|
|
Success = false;
|
|
|
|
} else {
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.AnalysisStoreOpt = Value;
|
2011-12-23 11:05:38 +08:00
|
|
|
}
|
2009-12-01 11:16:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (Arg *A = Args.getLastArg(OPT_analyzer_constraints)) {
|
2012-11-01 12:30:05 +08:00
|
|
|
StringRef Name = A->getValue();
|
2009-12-01 11:16:53 +08:00
|
|
|
AnalysisConstraints Value = llvm::StringSwitch<AnalysisConstraints>(Name)
|
|
|
|
#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \
|
|
|
|
.Case(CMDFLAG, NAME##Model)
|
2012-08-31 12:35:58 +08:00
|
|
|
#include "clang/StaticAnalyzer/Core/Analyses.def"
|
2009-12-01 11:16:53 +08:00
|
|
|
.Default(NumConstraints);
|
2011-12-23 11:05:38 +08:00
|
|
|
if (Value == NumConstraints) {
|
2009-12-01 11:16:53 +08:00
|
|
|
Diags.Report(diag::err_drv_invalid_value)
|
2010-06-10 06:30:54 +08:00
|
|
|
<< A->getAsString(Args) << Name;
|
2011-12-23 11:05:38 +08:00
|
|
|
Success = false;
|
|
|
|
} else {
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.AnalysisConstraintsOpt = Value;
|
2011-12-23 11:05:38 +08:00
|
|
|
}
|
2009-12-01 11:16:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (Arg *A = Args.getLastArg(OPT_analyzer_output)) {
|
2012-11-01 12:30:05 +08:00
|
|
|
StringRef Name = A->getValue();
|
2009-12-01 11:16:53 +08:00
|
|
|
AnalysisDiagClients Value = llvm::StringSwitch<AnalysisDiagClients>(Name)
|
2013-08-16 09:06:30 +08:00
|
|
|
#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) \
|
2009-12-01 11:16:53 +08:00
|
|
|
.Case(CMDFLAG, PD_##NAME)
|
2012-08-31 12:35:58 +08:00
|
|
|
#include "clang/StaticAnalyzer/Core/Analyses.def"
|
2009-12-01 11:16:53 +08:00
|
|
|
.Default(NUM_ANALYSIS_DIAG_CLIENTS);
|
2011-12-23 11:05:38 +08:00
|
|
|
if (Value == NUM_ANALYSIS_DIAG_CLIENTS) {
|
2009-12-01 11:16:53 +08:00
|
|
|
Diags.Report(diag::err_drv_invalid_value)
|
2010-06-10 06:30:54 +08:00
|
|
|
<< A->getAsString(Args) << Name;
|
2011-12-23 11:05:38 +08:00
|
|
|
Success = false;
|
|
|
|
} else {
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.AnalysisDiagOpt = Value;
|
2011-12-23 11:05:38 +08:00
|
|
|
}
|
2009-12-01 11:16:53 +08:00
|
|
|
}
|
|
|
|
|
2011-09-30 10:03:00 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_analyzer_purge)) {
|
2012-11-01 12:30:05 +08:00
|
|
|
StringRef Name = A->getValue();
|
2011-09-30 10:03:00 +08:00
|
|
|
AnalysisPurgeMode Value = llvm::StringSwitch<AnalysisPurgeMode>(Name)
|
|
|
|
#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) \
|
|
|
|
.Case(CMDFLAG, NAME)
|
2012-08-31 12:35:58 +08:00
|
|
|
#include "clang/StaticAnalyzer/Core/Analyses.def"
|
2011-09-30 10:03:00 +08:00
|
|
|
.Default(NumPurgeModes);
|
2011-12-23 11:05:38 +08:00
|
|
|
if (Value == NumPurgeModes) {
|
2011-09-30 10:03:00 +08:00
|
|
|
Diags.Report(diag::err_drv_invalid_value)
|
|
|
|
<< A->getAsString(Args) << Name;
|
2011-12-23 11:05:38 +08:00
|
|
|
Success = false;
|
|
|
|
} else {
|
2011-09-30 10:03:00 +08:00
|
|
|
Opts.AnalysisPurgeOpt = Value;
|
2011-12-23 11:05:38 +08:00
|
|
|
}
|
2011-09-30 10:03:00 +08:00
|
|
|
}
|
|
|
|
|
2012-03-09 07:16:35 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_analyzer_inlining_mode)) {
|
2012-11-01 12:30:05 +08:00
|
|
|
StringRef Name = A->getValue();
|
2012-03-09 07:16:35 +08:00
|
|
|
AnalysisInliningMode Value = llvm::StringSwitch<AnalysisInliningMode>(Name)
|
|
|
|
#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) \
|
|
|
|
.Case(CMDFLAG, NAME)
|
2012-08-31 12:35:58 +08:00
|
|
|
#include "clang/StaticAnalyzer/Core/Analyses.def"
|
2012-03-09 07:16:35 +08:00
|
|
|
.Default(NumInliningModes);
|
|
|
|
if (Value == NumInliningModes) {
|
|
|
|
Diags.Report(diag::err_drv_invalid_value)
|
|
|
|
<< A->getAsString(Args) << Name;
|
|
|
|
Success = false;
|
|
|
|
} else {
|
|
|
|
Opts.InliningMode = Value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-25 08:09:51 +08:00
|
|
|
Opts.ShowCheckerHelp = Args.hasArg(OPT_analyzer_checker_help);
|
2019-05-24 05:46:51 +08:00
|
|
|
Opts.ShowCheckerHelpAlpha = Args.hasArg(OPT_analyzer_checker_help_alpha);
|
|
|
|
Opts.ShowCheckerHelpDeveloper =
|
|
|
|
Args.hasArg(OPT_analyzer_checker_help_developer);
|
2019-05-24 06:52:09 +08:00
|
|
|
|
2019-05-24 04:47:28 +08:00
|
|
|
Opts.ShowCheckerOptionList = Args.hasArg(OPT_analyzer_checker_option_help);
|
2019-05-24 06:52:09 +08:00
|
|
|
Opts.ShowCheckerOptionAlphaList =
|
|
|
|
Args.hasArg(OPT_analyzer_checker_option_help_alpha);
|
2019-05-24 06:07:16 +08:00
|
|
|
Opts.ShowCheckerOptionDeveloperList =
|
|
|
|
Args.hasArg(OPT_analyzer_checker_option_help_developer);
|
2019-05-24 06:52:09 +08:00
|
|
|
|
2018-11-02 23:59:37 +08:00
|
|
|
Opts.ShowConfigOptionsList = Args.hasArg(OPT_analyzer_config_help);
|
2016-08-08 21:41:04 +08:00
|
|
|
Opts.ShowEnabledCheckerList = Args.hasArg(OPT_analyzer_list_enabled_checkers);
|
2018-12-01 05:24:31 +08:00
|
|
|
Opts.ShouldEmitErrorsOnInvalidConfigValue =
|
|
|
|
/* negated */!llvm::StringSwitch<bool>(
|
|
|
|
Args.getLastArgValue(OPT_analyzer_config_compatibility_mode))
|
|
|
|
.Case("true", true)
|
|
|
|
.Case("false", false)
|
|
|
|
.Default(false);
|
2014-08-30 04:01:38 +08:00
|
|
|
Opts.DisableAllChecks = Args.hasArg(OPT_analyzer_disable_all_checks);
|
|
|
|
|
2012-08-31 03:26:53 +08:00
|
|
|
Opts.visualizeExplodedGraphWithGraphViz =
|
|
|
|
Args.hasArg(OPT_analyzer_viz_egraph_graphviz);
|
2018-09-29 02:49:21 +08:00
|
|
|
Opts.DumpExplodedGraphTo = Args.getLastArgValue(OPT_analyzer_dump_egraph);
|
2012-03-29 03:59:16 +08:00
|
|
|
Opts.NoRetryExhausted = Args.hasArg(OPT_analyzer_disable_retry_exhausted);
|
2019-06-08 07:34:00 +08:00
|
|
|
Opts.AnalyzerWerror = Args.hasArg(OPT_analyzer_werror);
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.AnalyzeAll = Args.hasArg(OPT_analyzer_opt_analyze_headers);
|
|
|
|
Opts.AnalyzerDisplayProgress = Args.hasArg(OPT_analyzer_display_progress);
|
2009-12-08 06:06:12 +08:00
|
|
|
Opts.AnalyzeNestedBlocks =
|
|
|
|
Args.hasArg(OPT_analyzer_opt_analyze_nested_blocks);
|
2010-05-21 00:54:55 +08:00
|
|
|
Opts.AnalyzeSpecificFunction = Args.getLastArgValue(OPT_analyze_function);
|
2010-08-03 08:09:51 +08:00
|
|
|
Opts.UnoptimizedCFG = Args.hasArg(OPT_analysis_UnoptimizedCFG);
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.TrimGraph = Args.hasArg(OPT_trim_egraph);
|
2013-06-15 01:17:23 +08:00
|
|
|
Opts.maxBlockVisitOnPath =
|
|
|
|
getLastArgIntValue(Args, OPT_analyzer_max_loop, 4, Diags);
|
2012-02-28 05:33:16 +08:00
|
|
|
Opts.PrintStats = Args.hasArg(OPT_analyzer_stats);
|
2012-03-03 03:05:03 +08:00
|
|
|
Opts.InlineMaxStackDepth =
|
2013-06-15 01:17:23 +08:00
|
|
|
getLastArgIntValue(Args, OPT_analyzer_inline_max_stack_depth,
|
|
|
|
Opts.InlineMaxStackDepth, Diags);
|
2011-02-15 02:13:31 +08:00
|
|
|
|
2019-08-16 09:53:14 +08:00
|
|
|
Opts.CheckersAndPackages.clear();
|
2015-06-09 09:57:17 +08:00
|
|
|
for (const Arg *A :
|
|
|
|
Args.filtered(OPT_analyzer_checker, OPT_analyzer_disable_checker)) {
|
2011-02-15 02:13:31 +08:00
|
|
|
A->claim();
|
2019-08-16 09:53:14 +08:00
|
|
|
bool IsEnabled = A->getOption().getID() == OPT_analyzer_checker;
|
2011-02-24 16:42:20 +08:00
|
|
|
// We can have a list of comma separated checker names, e.g:
|
|
|
|
// '-analyzer-checker=cocoa,unix'
|
2019-08-16 09:53:14 +08:00
|
|
|
StringRef CheckerAndPackageList = A->getValue();
|
|
|
|
SmallVector<StringRef, 16> CheckersAndPackages;
|
|
|
|
CheckerAndPackageList.split(CheckersAndPackages, ",");
|
|
|
|
for (const StringRef CheckerOrPackage : CheckersAndPackages)
|
|
|
|
Opts.CheckersAndPackages.emplace_back(CheckerOrPackage, IsEnabled);
|
2011-02-15 02:13:31 +08:00
|
|
|
}
|
2015-02-25 05:45:33 +08:00
|
|
|
|
2012-08-29 13:55:00 +08:00
|
|
|
// Go through the analyzer configuration options.
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *A : Args.filtered(OPT_analyzer_config)) {
|
2018-12-01 05:24:31 +08:00
|
|
|
|
2012-08-29 13:55:00 +08:00
|
|
|
// We can have a list of comma separated config names, e.g:
|
2012-08-30 13:49:16 +08:00
|
|
|
// '-analyzer-config key1=val1,key2=val2'
|
2012-11-01 12:30:05 +08:00
|
|
|
StringRef configList = A->getValue();
|
2012-08-29 13:55:00 +08:00
|
|
|
SmallVector<StringRef, 4> configVals;
|
|
|
|
configList.split(configVals, ",");
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto &configVal : configVals) {
|
2012-08-29 13:55:00 +08:00
|
|
|
StringRef key, val;
|
2018-03-27 05:45:04 +08:00
|
|
|
std::tie(key, val) = configVal.split("=");
|
2012-08-29 13:55:00 +08:00
|
|
|
if (val.empty()) {
|
|
|
|
Diags.Report(SourceLocation(),
|
2018-03-27 05:45:04 +08:00
|
|
|
diag::err_analyzer_config_no_value) << configVal;
|
2012-08-29 13:55:00 +08:00
|
|
|
Success = false;
|
|
|
|
break;
|
|
|
|
}
|
2012-08-30 13:49:16 +08:00
|
|
|
if (val.find('=') != StringRef::npos) {
|
2012-08-29 13:55:00 +08:00
|
|
|
Diags.Report(SourceLocation(),
|
|
|
|
diag::err_analyzer_config_multiple_values)
|
2018-03-27 05:45:04 +08:00
|
|
|
<< configVal;
|
2012-08-29 13:55:00 +08:00
|
|
|
Success = false;
|
|
|
|
break;
|
|
|
|
}
|
2018-12-01 05:24:31 +08:00
|
|
|
|
|
|
|
// TODO: Check checker options too, possibly in CheckerRegistry.
|
|
|
|
// Leave unknown non-checker configs unclaimed.
|
|
|
|
if (!key.contains(":") && Opts.isUnknownAnalyzerConfig(key)) {
|
|
|
|
if (Opts.ShouldEmitErrorsOnInvalidConfigValue)
|
|
|
|
Diags.Report(diag::err_analyzer_config_unknown) << key;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
A->claim();
|
2012-08-29 13:55:00 +08:00
|
|
|
Opts.Config[key] = val;
|
|
|
|
}
|
|
|
|
}
|
2011-12-23 11:05:38 +08:00
|
|
|
|
2018-12-01 05:24:31 +08:00
|
|
|
if (Opts.ShouldEmitErrorsOnInvalidConfigValue)
|
|
|
|
parseAnalyzerConfigs(Opts, &Diags);
|
|
|
|
else
|
|
|
|
parseAnalyzerConfigs(Opts, nullptr);
|
[analyzer] Evaluate all non-checker config options before analysis
In earlier patches regarding AnalyzerOptions, a lot of effort went into
gathering all config options, and changing the interface so that potential
misuse can be eliminited.
Up until this point, AnalyzerOptions only evaluated an option when it was
querried. For example, if we had a "-no-false-positives" flag, AnalyzerOptions
would store an Optional field for it that would be None up until somewhere in
the code until the flag's getter function is called.
However, now that we're confident that we've gathered all configs, we can
evaluate off of them before analysis, so we can emit a error on invalid input
even if that prticular flag will not matter in that particular run of the
analyzer. Another very big benefit of this is that debug.ConfigDumper will now
show the value of all configs every single time.
Also, almost all options related class have a similar interface, so uniformity
is also a benefit.
The implementation for errors on invalid input will be commited shorty.
Differential Revision: https://reviews.llvm.org/D53692
llvm-svn: 348031
2018-12-01 04:44:00 +08:00
|
|
|
|
2018-01-24 03:28:52 +08:00
|
|
|
llvm::raw_string_ostream os(Opts.FullCompilerInvocation);
|
2018-03-27 05:45:04 +08:00
|
|
|
for (unsigned i = 0; i < Args.getNumInputArgStrings(); ++i) {
|
2018-01-24 03:28:52 +08:00
|
|
|
if (i != 0)
|
|
|
|
os << " ";
|
|
|
|
os << Args.getArgString(i);
|
|
|
|
}
|
|
|
|
os.flush();
|
|
|
|
|
2011-12-23 11:05:38 +08:00
|
|
|
return Success;
|
2009-12-01 11:16:53 +08:00
|
|
|
}
|
|
|
|
|
[analyzer] Evaluate all non-checker config options before analysis
In earlier patches regarding AnalyzerOptions, a lot of effort went into
gathering all config options, and changing the interface so that potential
misuse can be eliminited.
Up until this point, AnalyzerOptions only evaluated an option when it was
querried. For example, if we had a "-no-false-positives" flag, AnalyzerOptions
would store an Optional field for it that would be None up until somewhere in
the code until the flag's getter function is called.
However, now that we're confident that we've gathered all configs, we can
evaluate off of them before analysis, so we can emit a error on invalid input
even if that prticular flag will not matter in that particular run of the
analyzer. Another very big benefit of this is that debug.ConfigDumper will now
show the value of all configs every single time.
Also, almost all options related class have a similar interface, so uniformity
is also a benefit.
The implementation for errors on invalid input will be commited shorty.
Differential Revision: https://reviews.llvm.org/D53692
llvm-svn: 348031
2018-12-01 04:44:00 +08:00
|
|
|
static StringRef getStringOption(AnalyzerOptions::ConfigTable &Config,
|
|
|
|
StringRef OptionName, StringRef DefaultVal) {
|
|
|
|
return Config.insert({OptionName, DefaultVal}).first->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void initOption(AnalyzerOptions::ConfigTable &Config,
|
2018-12-01 05:24:31 +08:00
|
|
|
DiagnosticsEngine *Diags,
|
[analyzer] Evaluate all non-checker config options before analysis
In earlier patches regarding AnalyzerOptions, a lot of effort went into
gathering all config options, and changing the interface so that potential
misuse can be eliminited.
Up until this point, AnalyzerOptions only evaluated an option when it was
querried. For example, if we had a "-no-false-positives" flag, AnalyzerOptions
would store an Optional field for it that would be None up until somewhere in
the code until the flag's getter function is called.
However, now that we're confident that we've gathered all configs, we can
evaluate off of them before analysis, so we can emit a error on invalid input
even if that prticular flag will not matter in that particular run of the
analyzer. Another very big benefit of this is that debug.ConfigDumper will now
show the value of all configs every single time.
Also, almost all options related class have a similar interface, so uniformity
is also a benefit.
The implementation for errors on invalid input will be commited shorty.
Differential Revision: https://reviews.llvm.org/D53692
llvm-svn: 348031
2018-12-01 04:44:00 +08:00
|
|
|
StringRef &OptionField, StringRef Name,
|
|
|
|
StringRef DefaultVal) {
|
2018-12-01 05:24:31 +08:00
|
|
|
// String options may be known to invalid (e.g. if the expected string is a
|
|
|
|
// file name, but the file does not exist), those will have to be checked in
|
|
|
|
// parseConfigs.
|
[analyzer] Evaluate all non-checker config options before analysis
In earlier patches regarding AnalyzerOptions, a lot of effort went into
gathering all config options, and changing the interface so that potential
misuse can be eliminited.
Up until this point, AnalyzerOptions only evaluated an option when it was
querried. For example, if we had a "-no-false-positives" flag, AnalyzerOptions
would store an Optional field for it that would be None up until somewhere in
the code until the flag's getter function is called.
However, now that we're confident that we've gathered all configs, we can
evaluate off of them before analysis, so we can emit a error on invalid input
even if that prticular flag will not matter in that particular run of the
analyzer. Another very big benefit of this is that debug.ConfigDumper will now
show the value of all configs every single time.
Also, almost all options related class have a similar interface, so uniformity
is also a benefit.
The implementation for errors on invalid input will be commited shorty.
Differential Revision: https://reviews.llvm.org/D53692
llvm-svn: 348031
2018-12-01 04:44:00 +08:00
|
|
|
OptionField = getStringOption(Config, Name, DefaultVal);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void initOption(AnalyzerOptions::ConfigTable &Config,
|
2018-12-01 05:24:31 +08:00
|
|
|
DiagnosticsEngine *Diags,
|
[analyzer] Evaluate all non-checker config options before analysis
In earlier patches regarding AnalyzerOptions, a lot of effort went into
gathering all config options, and changing the interface so that potential
misuse can be eliminited.
Up until this point, AnalyzerOptions only evaluated an option when it was
querried. For example, if we had a "-no-false-positives" flag, AnalyzerOptions
would store an Optional field for it that would be None up until somewhere in
the code until the flag's getter function is called.
However, now that we're confident that we've gathered all configs, we can
evaluate off of them before analysis, so we can emit a error on invalid input
even if that prticular flag will not matter in that particular run of the
analyzer. Another very big benefit of this is that debug.ConfigDumper will now
show the value of all configs every single time.
Also, almost all options related class have a similar interface, so uniformity
is also a benefit.
The implementation for errors on invalid input will be commited shorty.
Differential Revision: https://reviews.llvm.org/D53692
llvm-svn: 348031
2018-12-01 04:44:00 +08:00
|
|
|
bool &OptionField, StringRef Name, bool DefaultVal) {
|
2018-12-01 05:24:31 +08:00
|
|
|
auto PossiblyInvalidVal = llvm::StringSwitch<Optional<bool>>(
|
|
|
|
getStringOption(Config, Name, (DefaultVal ? "true" : "false")))
|
[analyzer] Evaluate all non-checker config options before analysis
In earlier patches regarding AnalyzerOptions, a lot of effort went into
gathering all config options, and changing the interface so that potential
misuse can be eliminited.
Up until this point, AnalyzerOptions only evaluated an option when it was
querried. For example, if we had a "-no-false-positives" flag, AnalyzerOptions
would store an Optional field for it that would be None up until somewhere in
the code until the flag's getter function is called.
However, now that we're confident that we've gathered all configs, we can
evaluate off of them before analysis, so we can emit a error on invalid input
even if that prticular flag will not matter in that particular run of the
analyzer. Another very big benefit of this is that debug.ConfigDumper will now
show the value of all configs every single time.
Also, almost all options related class have a similar interface, so uniformity
is also a benefit.
The implementation for errors on invalid input will be commited shorty.
Differential Revision: https://reviews.llvm.org/D53692
llvm-svn: 348031
2018-12-01 04:44:00 +08:00
|
|
|
.Case("true", true)
|
|
|
|
.Case("false", false)
|
2018-12-01 05:24:31 +08:00
|
|
|
.Default(None);
|
|
|
|
|
|
|
|
if (!PossiblyInvalidVal) {
|
|
|
|
if (Diags)
|
|
|
|
Diags->Report(diag::err_analyzer_config_invalid_input)
|
|
|
|
<< Name << "a boolean";
|
|
|
|
else
|
|
|
|
OptionField = DefaultVal;
|
|
|
|
} else
|
|
|
|
OptionField = PossiblyInvalidVal.getValue();
|
[analyzer] Evaluate all non-checker config options before analysis
In earlier patches regarding AnalyzerOptions, a lot of effort went into
gathering all config options, and changing the interface so that potential
misuse can be eliminited.
Up until this point, AnalyzerOptions only evaluated an option when it was
querried. For example, if we had a "-no-false-positives" flag, AnalyzerOptions
would store an Optional field for it that would be None up until somewhere in
the code until the flag's getter function is called.
However, now that we're confident that we've gathered all configs, we can
evaluate off of them before analysis, so we can emit a error on invalid input
even if that prticular flag will not matter in that particular run of the
analyzer. Another very big benefit of this is that debug.ConfigDumper will now
show the value of all configs every single time.
Also, almost all options related class have a similar interface, so uniformity
is also a benefit.
The implementation for errors on invalid input will be commited shorty.
Differential Revision: https://reviews.llvm.org/D53692
llvm-svn: 348031
2018-12-01 04:44:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void initOption(AnalyzerOptions::ConfigTable &Config,
|
2018-12-01 05:24:31 +08:00
|
|
|
DiagnosticsEngine *Diags,
|
[analyzer] Evaluate all non-checker config options before analysis
In earlier patches regarding AnalyzerOptions, a lot of effort went into
gathering all config options, and changing the interface so that potential
misuse can be eliminited.
Up until this point, AnalyzerOptions only evaluated an option when it was
querried. For example, if we had a "-no-false-positives" flag, AnalyzerOptions
would store an Optional field for it that would be None up until somewhere in
the code until the flag's getter function is called.
However, now that we're confident that we've gathered all configs, we can
evaluate off of them before analysis, so we can emit a error on invalid input
even if that prticular flag will not matter in that particular run of the
analyzer. Another very big benefit of this is that debug.ConfigDumper will now
show the value of all configs every single time.
Also, almost all options related class have a similar interface, so uniformity
is also a benefit.
The implementation for errors on invalid input will be commited shorty.
Differential Revision: https://reviews.llvm.org/D53692
llvm-svn: 348031
2018-12-01 04:44:00 +08:00
|
|
|
unsigned &OptionField, StringRef Name,
|
|
|
|
unsigned DefaultVal) {
|
2018-12-01 05:24:31 +08:00
|
|
|
|
[analyzer] Evaluate all non-checker config options before analysis
In earlier patches regarding AnalyzerOptions, a lot of effort went into
gathering all config options, and changing the interface so that potential
misuse can be eliminited.
Up until this point, AnalyzerOptions only evaluated an option when it was
querried. For example, if we had a "-no-false-positives" flag, AnalyzerOptions
would store an Optional field for it that would be None up until somewhere in
the code until the flag's getter function is called.
However, now that we're confident that we've gathered all configs, we can
evaluate off of them before analysis, so we can emit a error on invalid input
even if that prticular flag will not matter in that particular run of the
analyzer. Another very big benefit of this is that debug.ConfigDumper will now
show the value of all configs every single time.
Also, almost all options related class have a similar interface, so uniformity
is also a benefit.
The implementation for errors on invalid input will be commited shorty.
Differential Revision: https://reviews.llvm.org/D53692
llvm-svn: 348031
2018-12-01 04:44:00 +08:00
|
|
|
OptionField = DefaultVal;
|
|
|
|
bool HasFailed = getStringOption(Config, Name, std::to_string(DefaultVal))
|
[analyzer][NFC] Reimplement checker options
TL;DR:
* Add checker and package options to the TableGen files
* Added a new class called CmdLineOption, and both Package and Checker recieved
a list<CmdLineOption> field.
* Added every existing checker and package option to Checkers.td.
* The CheckerRegistry class
* Received some comments to most of it's inline classes
* Received the CmdLineOption and PackageInfo inline classes, a list of
CmdLineOption was added to CheckerInfo and PackageInfo
* Added addCheckerOption and addPackageOption
* Added a new field called Packages, used in addPackageOptions, filled up in
addPackage
Detailed description:
In the last couple months, a lot of effort was put into tightening the
analyzer's command line interface. The main issue is that it's spectacularly
easy to mess up a lenghty enough invocation of the analyzer, and the user was
given no warnings or errors at all in that case.
We can divide the effort of resolving this into several chapters:
* Non-checker analyzer configurations:
Gather every analyzer configuration into a dedicated file. Emit errors for
non-existent configurations or incorrect values. Be able to list these
configurations. Tighten AnalyzerOptions interface to disallow making such
a mistake in the future.
* Fix the "Checker Naming Bug" by reimplementing checker dependencies:
When cplusplus.InnerPointer was enabled, it implicitly registered
unix.Malloc, which implicitly registered some sort of a modeling checker
from the CStringChecker family. This resulted in all of these checker
objects recieving the name "cplusplus.InnerPointer", making AnalyzerOptions
asking for the wrong checker options from the command line:
cplusplus.InnerPointer:Optimisic
istead of
unix.Malloc:Optimistic.
This was resolved by making CheckerRegistry responsible for checker
dependency handling, instead of checkers themselves.
* Checker options: (this patch included!)
Same as the first item, but for checkers.
(+ minor fixes here and there, and everything else that is yet to come)
There were several issues regarding checker options, that non-checker
configurations didn't suffer from: checker plugins are loaded runtime, and they
could add new checkers and new options, meaning that unlike for non-checker
configurations, we can't collect every checker option purely by generating code.
Also, as seen from the "Checker Naming Bug" issue raised above, they are very
rarely used in practice, and all sorts of skeletons fell out of the closet while
working on this project.
They were extremely problematic for users as well, purely because of how long
they were. Consider the following monster of a checker option:
alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=false
While we were able to verify whether the checker itself (the part before the
colon) existed, any errors past that point were unreported, easily resulting
in 7+ hours of analyses going to waste.
This patch, similarly to how dependencies were reimplemented, uses TableGen to
register checker options into Checkers.td, so that Checkers.inc now contains
entries for both checker and package options. Using the preprocessor,
Checkers.inc is converted into code in CheckerRegistry, adding every builtin
(checkers and packages that have an entry in the Checkers.td file) checker and
package option to the registry. The new addPackageOption and addCheckerOption
functions expose the same functionality to statically-linked non-builtin and
plugin checkers and packages as well.
Emitting errors for incorrect user input, being able to list these options, and
some other functionalies will land in later patches.
Differential Revision: https://reviews.llvm.org/D57855
llvm-svn: 358752
2019-04-19 20:32:10 +08:00
|
|
|
.getAsInteger(0, OptionField);
|
2018-12-01 05:24:31 +08:00
|
|
|
if (Diags && HasFailed)
|
|
|
|
Diags->Report(diag::err_analyzer_config_invalid_input)
|
|
|
|
<< Name << "an unsigned";
|
[analyzer] Evaluate all non-checker config options before analysis
In earlier patches regarding AnalyzerOptions, a lot of effort went into
gathering all config options, and changing the interface so that potential
misuse can be eliminited.
Up until this point, AnalyzerOptions only evaluated an option when it was
querried. For example, if we had a "-no-false-positives" flag, AnalyzerOptions
would store an Optional field for it that would be None up until somewhere in
the code until the flag's getter function is called.
However, now that we're confident that we've gathered all configs, we can
evaluate off of them before analysis, so we can emit a error on invalid input
even if that prticular flag will not matter in that particular run of the
analyzer. Another very big benefit of this is that debug.ConfigDumper will now
show the value of all configs every single time.
Also, almost all options related class have a similar interface, so uniformity
is also a benefit.
The implementation for errors on invalid input will be commited shorty.
Differential Revision: https://reviews.llvm.org/D53692
llvm-svn: 348031
2018-12-01 04:44:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts,
|
2018-12-01 05:24:31 +08:00
|
|
|
DiagnosticsEngine *Diags) {
|
[analyzer] Evaluate all non-checker config options before analysis
In earlier patches regarding AnalyzerOptions, a lot of effort went into
gathering all config options, and changing the interface so that potential
misuse can be eliminited.
Up until this point, AnalyzerOptions only evaluated an option when it was
querried. For example, if we had a "-no-false-positives" flag, AnalyzerOptions
would store an Optional field for it that would be None up until somewhere in
the code until the flag's getter function is called.
However, now that we're confident that we've gathered all configs, we can
evaluate off of them before analysis, so we can emit a error on invalid input
even if that prticular flag will not matter in that particular run of the
analyzer. Another very big benefit of this is that debug.ConfigDumper will now
show the value of all configs every single time.
Also, almost all options related class have a similar interface, so uniformity
is also a benefit.
The implementation for errors on invalid input will be commited shorty.
Differential Revision: https://reviews.llvm.org/D53692
llvm-svn: 348031
2018-12-01 04:44:00 +08:00
|
|
|
// TODO: There's no need to store the entire configtable, it'd be plenty
|
|
|
|
// enough tostore checker options.
|
|
|
|
|
|
|
|
#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL) \
|
2018-12-01 05:24:31 +08:00
|
|
|
initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG, DEFAULT_VAL);
|
[analyzer] Evaluate all non-checker config options before analysis
In earlier patches regarding AnalyzerOptions, a lot of effort went into
gathering all config options, and changing the interface so that potential
misuse can be eliminited.
Up until this point, AnalyzerOptions only evaluated an option when it was
querried. For example, if we had a "-no-false-positives" flag, AnalyzerOptions
would store an Optional field for it that would be None up until somewhere in
the code until the flag's getter function is called.
However, now that we're confident that we've gathered all configs, we can
evaluate off of them before analysis, so we can emit a error on invalid input
even if that prticular flag will not matter in that particular run of the
analyzer. Another very big benefit of this is that debug.ConfigDumper will now
show the value of all configs every single time.
Also, almost all options related class have a similar interface, so uniformity
is also a benefit.
The implementation for errors on invalid input will be commited shorty.
Differential Revision: https://reviews.llvm.org/D53692
llvm-svn: 348031
2018-12-01 04:44:00 +08:00
|
|
|
|
|
|
|
#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \
|
|
|
|
SHALLOW_VAL, DEEP_VAL) \
|
|
|
|
switch (AnOpts.getUserMode()) { \
|
|
|
|
case UMK_Shallow: \
|
2018-12-01 05:24:31 +08:00
|
|
|
initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG, SHALLOW_VAL); \
|
[analyzer] Evaluate all non-checker config options before analysis
In earlier patches regarding AnalyzerOptions, a lot of effort went into
gathering all config options, and changing the interface so that potential
misuse can be eliminited.
Up until this point, AnalyzerOptions only evaluated an option when it was
querried. For example, if we had a "-no-false-positives" flag, AnalyzerOptions
would store an Optional field for it that would be None up until somewhere in
the code until the flag's getter function is called.
However, now that we're confident that we've gathered all configs, we can
evaluate off of them before analysis, so we can emit a error on invalid input
even if that prticular flag will not matter in that particular run of the
analyzer. Another very big benefit of this is that debug.ConfigDumper will now
show the value of all configs every single time.
Also, almost all options related class have a similar interface, so uniformity
is also a benefit.
The implementation for errors on invalid input will be commited shorty.
Differential Revision: https://reviews.llvm.org/D53692
llvm-svn: 348031
2018-12-01 04:44:00 +08:00
|
|
|
break; \
|
|
|
|
case UMK_Deep: \
|
2018-12-01 05:24:31 +08:00
|
|
|
initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG, DEEP_VAL); \
|
[analyzer] Evaluate all non-checker config options before analysis
In earlier patches regarding AnalyzerOptions, a lot of effort went into
gathering all config options, and changing the interface so that potential
misuse can be eliminited.
Up until this point, AnalyzerOptions only evaluated an option when it was
querried. For example, if we had a "-no-false-positives" flag, AnalyzerOptions
would store an Optional field for it that would be None up until somewhere in
the code until the flag's getter function is called.
However, now that we're confident that we've gathered all configs, we can
evaluate off of them before analysis, so we can emit a error on invalid input
even if that prticular flag will not matter in that particular run of the
analyzer. Another very big benefit of this is that debug.ConfigDumper will now
show the value of all configs every single time.
Also, almost all options related class have a similar interface, so uniformity
is also a benefit.
The implementation for errors on invalid input will be commited shorty.
Differential Revision: https://reviews.llvm.org/D53692
llvm-svn: 348031
2018-12-01 04:44:00 +08:00
|
|
|
break; \
|
|
|
|
} \
|
|
|
|
|
|
|
|
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
|
|
|
|
#undef ANALYZER_OPTION
|
|
|
|
#undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
|
2018-12-01 05:24:31 +08:00
|
|
|
|
|
|
|
// At this point, AnalyzerOptions is configured. Let's validate some options.
|
|
|
|
|
2019-08-16 09:53:14 +08:00
|
|
|
// FIXME: Here we try to validate the silenced checkers or packages are valid.
|
|
|
|
// The current approach only validates the registered checkers which does not
|
|
|
|
// contain the runtime enabled checkers and optimally we would validate both.
|
|
|
|
if (!AnOpts.RawSilencedCheckersAndPackages.empty()) {
|
|
|
|
std::vector<StringRef> Checkers =
|
|
|
|
AnOpts.getRegisteredCheckers(/*IncludeExperimental=*/true);
|
|
|
|
std::vector<StringRef> Packages =
|
|
|
|
AnOpts.getRegisteredPackages(/*IncludeExperimental=*/true);
|
|
|
|
|
|
|
|
SmallVector<StringRef, 16> CheckersAndPackages;
|
|
|
|
AnOpts.RawSilencedCheckersAndPackages.split(CheckersAndPackages, ";");
|
|
|
|
|
|
|
|
for (const StringRef CheckerOrPackage : CheckersAndPackages) {
|
2019-08-24 20:17:49 +08:00
|
|
|
if (Diags) {
|
|
|
|
bool IsChecker = CheckerOrPackage.contains('.');
|
|
|
|
bool IsValidName =
|
|
|
|
IsChecker
|
|
|
|
? llvm::find(Checkers, CheckerOrPackage) != Checkers.end()
|
|
|
|
: llvm::find(Packages, CheckerOrPackage) != Packages.end();
|
|
|
|
|
|
|
|
if (!IsValidName)
|
|
|
|
Diags->Report(diag::err_unknown_analyzer_checker_or_package)
|
|
|
|
<< CheckerOrPackage;
|
|
|
|
}
|
2019-08-16 09:53:14 +08:00
|
|
|
|
|
|
|
AnOpts.SilencedCheckersAndPackages.emplace_back(CheckerOrPackage);
|
|
|
|
}
|
|
|
|
}
|
2019-08-24 20:17:49 +08:00
|
|
|
|
|
|
|
if (!Diags)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (AnOpts.ShouldTrackConditionsDebug && !AnOpts.ShouldTrackConditions)
|
|
|
|
Diags->Report(diag::err_analyzer_config_invalid_input)
|
|
|
|
<< "track-conditions-debug" << "'track-conditions' to also be enabled";
|
|
|
|
|
|
|
|
if (!AnOpts.CTUDir.empty() && !llvm::sys::fs::is_directory(AnOpts.CTUDir))
|
|
|
|
Diags->Report(diag::err_analyzer_config_invalid_input) << "ctu-dir"
|
|
|
|
<< "a filename";
|
|
|
|
|
|
|
|
if (!AnOpts.ModelPath.empty() &&
|
|
|
|
!llvm::sys::fs::is_directory(AnOpts.ModelPath))
|
|
|
|
Diags->Report(diag::err_analyzer_config_invalid_input) << "model-path"
|
|
|
|
<< "a filename";
|
[analyzer] Evaluate all non-checker config options before analysis
In earlier patches regarding AnalyzerOptions, a lot of effort went into
gathering all config options, and changing the interface so that potential
misuse can be eliminited.
Up until this point, AnalyzerOptions only evaluated an option when it was
querried. For example, if we had a "-no-false-positives" flag, AnalyzerOptions
would store an Optional field for it that would be None up until somewhere in
the code until the flag's getter function is called.
However, now that we're confident that we've gathered all configs, we can
evaluate off of them before analysis, so we can emit a error on invalid input
even if that prticular flag will not matter in that particular run of the
analyzer. Another very big benefit of this is that debug.ConfigDumper will now
show the value of all configs every single time.
Also, almost all options related class have a similar interface, so uniformity
is also a benefit.
The implementation for errors on invalid input will be commited shorty.
Differential Revision: https://reviews.llvm.org/D53692
llvm-svn: 348031
2018-12-01 04:44:00 +08:00
|
|
|
}
|
|
|
|
|
2012-01-25 08:20:29 +08:00
|
|
|
static bool ParseMigratorArgs(MigratorOptions &Opts, ArgList &Args) {
|
|
|
|
Opts.NoNSAllocReallocError = Args.hasArg(OPT_migrator_no_nsalloc_error);
|
2012-01-27 04:57:58 +08:00
|
|
|
Opts.NoFinalizeRemoval = Args.hasArg(OPT_migrator_no_finalize_removal);
|
2012-01-25 08:20:29 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-02-22 22:21:27 +08:00
|
|
|
static void ParseCommentArgs(CommentOptions &Opts, ArgList &Args) {
|
|
|
|
Opts.BlockCommandNames = Args.getAllArgValues(OPT_fcomment_block_commands);
|
2013-04-10 23:35:17 +08:00
|
|
|
Opts.ParseAllComments = Args.hasArg(OPT_fparse_all_comments);
|
2013-02-22 22:21:27 +08:00
|
|
|
}
|
|
|
|
|
2014-05-08 10:28:32 +08:00
|
|
|
static StringRef getCodeModel(ArgList &Args, DiagnosticsEngine &Diags) {
|
|
|
|
if (Arg *A = Args.getLastArg(OPT_mcode_model)) {
|
|
|
|
StringRef Value = A->getValue();
|
|
|
|
if (Value == "small" || Value == "kernel" || Value == "medium" ||
|
2018-08-22 19:34:28 +08:00
|
|
|
Value == "large" || Value == "tiny")
|
2014-05-08 10:28:32 +08:00
|
|
|
return Value;
|
|
|
|
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Value;
|
|
|
|
}
|
|
|
|
return "default";
|
|
|
|
}
|
|
|
|
|
2018-01-18 08:20:03 +08:00
|
|
|
static llvm::Reloc::Model getRelocModel(ArgList &Args,
|
|
|
|
DiagnosticsEngine &Diags) {
|
2017-04-02 05:07:07 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_mrelocation_model)) {
|
|
|
|
StringRef Value = A->getValue();
|
2018-01-18 08:20:03 +08:00
|
|
|
auto RM = llvm::StringSwitch<llvm::Optional<llvm::Reloc::Model>>(Value)
|
|
|
|
.Case("static", llvm::Reloc::Static)
|
|
|
|
.Case("pic", llvm::Reloc::PIC_)
|
|
|
|
.Case("ropi", llvm::Reloc::ROPI)
|
|
|
|
.Case("rwpi", llvm::Reloc::RWPI)
|
|
|
|
.Case("ropi-rwpi", llvm::Reloc::ROPI_RWPI)
|
|
|
|
.Case("dynamic-no-pic", llvm::Reloc::DynamicNoPIC)
|
|
|
|
.Default(None);
|
|
|
|
if (RM.hasValue())
|
|
|
|
return *RM;
|
2017-04-02 05:07:07 +08:00
|
|
|
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Value;
|
|
|
|
}
|
2018-01-18 08:20:03 +08:00
|
|
|
return llvm::Reloc::PIC_;
|
2017-04-02 05:07:07 +08:00
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Create a new Regex instance out of the string value in \p RpassArg.
|
2014-05-30 03:55:06 +08:00
|
|
|
/// It returns a pointer to the newly generated Regex instance.
|
|
|
|
static std::shared_ptr<llvm::Regex>
|
|
|
|
GenerateOptimizationRemarkRegex(DiagnosticsEngine &Diags, ArgList &Args,
|
|
|
|
Arg *RpassArg) {
|
|
|
|
StringRef Val = RpassArg->getValue();
|
|
|
|
std::string RegexError;
|
|
|
|
std::shared_ptr<llvm::Regex> Pattern = std::make_shared<llvm::Regex>(Val);
|
|
|
|
if (!Pattern->isValid(RegexError)) {
|
|
|
|
Diags.Report(diag::err_drv_optimization_remark_pattern)
|
|
|
|
<< RegexError << RpassArg->getAsString(Args);
|
|
|
|
Pattern.reset();
|
|
|
|
}
|
|
|
|
return Pattern;
|
|
|
|
}
|
|
|
|
|
2015-06-13 15:11:40 +08:00
|
|
|
static bool parseDiagnosticLevelMask(StringRef FlagName,
|
|
|
|
const std::vector<std::string> &Levels,
|
|
|
|
DiagnosticsEngine *Diags,
|
|
|
|
DiagnosticLevelMask &M) {
|
|
|
|
bool Success = true;
|
|
|
|
for (const auto &Level : Levels) {
|
|
|
|
DiagnosticLevelMask const PM =
|
|
|
|
llvm::StringSwitch<DiagnosticLevelMask>(Level)
|
|
|
|
.Case("note", DiagnosticLevelMask::Note)
|
|
|
|
.Case("remark", DiagnosticLevelMask::Remark)
|
|
|
|
.Case("warning", DiagnosticLevelMask::Warning)
|
|
|
|
.Case("error", DiagnosticLevelMask::Error)
|
|
|
|
.Default(DiagnosticLevelMask::None);
|
|
|
|
if (PM == DiagnosticLevelMask::None) {
|
|
|
|
Success = false;
|
|
|
|
if (Diags)
|
|
|
|
Diags->Report(diag::err_drv_invalid_value) << FlagName << Level;
|
|
|
|
}
|
|
|
|
M = M | PM;
|
|
|
|
}
|
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
Reimplement -fsanitize-recover family of flags.
Introduce the following -fsanitize-recover flags:
- -fsanitize-recover=<list>: Enable recovery for selected checks or
group of checks. It is forbidden to explicitly list unrecoverable
sanitizers here (that is, "address", "unreachable", "return").
- -fno-sanitize-recover=<list>: Disable recovery for selected checks or
group of checks.
- -f(no-)?sanitize-recover is now a synonym for
-f(no-)?sanitize-recover=undefined,integer and will soon be deprecated.
These flags are parsed left to right, and mask of "recoverable"
sanitizer is updated accordingly, much like what we do for -fsanitize= flags.
-fsanitize= and -fsanitize-recover= flag families are independent.
CodeGen change: If there is a single UBSan handler function, responsible
for implementing multiple checks, which have different recoverable setting,
then we emit two handler calls instead of one:
the first one for the set of "unrecoverable" checks, another one - for
set of "recoverable" checks. If all checks implemented by a handler have the
same recoverability setting, then the generated code will be the same.
llvm-svn: 225719
2015-01-13 06:39:12 +08:00
|
|
|
static void parseSanitizerKinds(StringRef FlagName,
|
|
|
|
const std::vector<std::string> &Sanitizers,
|
|
|
|
DiagnosticsEngine &Diags, SanitizerSet &S) {
|
|
|
|
for (const auto &Sanitizer : Sanitizers) {
|
2015-05-12 05:39:20 +08:00
|
|
|
SanitizerMask K = parseSanitizerValue(Sanitizer, /*AllowGroups=*/false);
|
2019-03-01 18:05:15 +08:00
|
|
|
if (K == SanitizerMask())
|
Reimplement -fsanitize-recover family of flags.
Introduce the following -fsanitize-recover flags:
- -fsanitize-recover=<list>: Enable recovery for selected checks or
group of checks. It is forbidden to explicitly list unrecoverable
sanitizers here (that is, "address", "unreachable", "return").
- -fno-sanitize-recover=<list>: Disable recovery for selected checks or
group of checks.
- -f(no-)?sanitize-recover is now a synonym for
-f(no-)?sanitize-recover=undefined,integer and will soon be deprecated.
These flags are parsed left to right, and mask of "recoverable"
sanitizer is updated accordingly, much like what we do for -fsanitize= flags.
-fsanitize= and -fsanitize-recover= flag families are independent.
CodeGen change: If there is a single UBSan handler function, responsible
for implementing multiple checks, which have different recoverable setting,
then we emit two handler calls instead of one:
the first one for the set of "unrecoverable" checks, another one - for
set of "recoverable" checks. If all checks implemented by a handler have the
same recoverability setting, then the generated code will be the same.
llvm-svn: 225719
2015-01-13 06:39:12 +08:00
|
|
|
Diags.Report(diag::err_drv_invalid_value) << FlagName << Sanitizer;
|
|
|
|
else
|
|
|
|
S.set(K, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-13 10:31:58 +08:00
|
|
|
static void parseXRayInstrumentationBundle(StringRef FlagName, StringRef Bundle,
|
|
|
|
ArgList &Args, DiagnosticsEngine &D,
|
|
|
|
XRayInstrSet &S) {
|
|
|
|
llvm::SmallVector<StringRef, 2> BundleParts;
|
|
|
|
llvm::SplitString(Bundle, BundleParts, ",");
|
|
|
|
for (const auto B : BundleParts) {
|
|
|
|
auto Mask = parseXRayInstrValue(B);
|
|
|
|
if (Mask == XRayInstrKind::None)
|
|
|
|
if (B != "none")
|
|
|
|
D.Report(diag::err_drv_invalid_value) << FlagName << Bundle;
|
|
|
|
else
|
|
|
|
S.Mask = Mask;
|
|
|
|
else if (Mask == XRayInstrKind::All)
|
|
|
|
S.Mask = Mask;
|
|
|
|
else
|
|
|
|
S.set(Mask, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-03 04:59:36 +08:00
|
|
|
// Set the profile kind for fprofile-instrument.
|
|
|
|
static void setPGOInstrumentor(CodeGenOptions &Opts, ArgList &Args,
|
|
|
|
DiagnosticsEngine &Diags) {
|
|
|
|
Arg *A = Args.getLastArg(OPT_fprofile_instrument_EQ);
|
|
|
|
if (A == nullptr)
|
|
|
|
return;
|
|
|
|
StringRef S = A->getValue();
|
|
|
|
unsigned I = llvm::StringSwitch<unsigned>(S)
|
|
|
|
.Case("none", CodeGenOptions::ProfileNone)
|
|
|
|
.Case("clang", CodeGenOptions::ProfileClangInstr)
|
|
|
|
.Case("llvm", CodeGenOptions::ProfileIRInstr)
|
2019-03-05 04:21:31 +08:00
|
|
|
.Case("csllvm", CodeGenOptions::ProfileCSIRInstr)
|
2016-03-03 04:59:36 +08:00
|
|
|
.Default(~0U);
|
|
|
|
if (I == ~0U) {
|
|
|
|
Diags.Report(diag::err_drv_invalid_pgo_instrumentor) << A->getAsString(Args)
|
|
|
|
<< S;
|
|
|
|
return;
|
|
|
|
}
|
2018-03-27 05:45:04 +08:00
|
|
|
auto Instrumentor = static_cast<CodeGenOptions::ProfileInstrKind>(I);
|
2016-03-03 04:59:36 +08:00
|
|
|
Opts.setProfileInstr(Instrumentor);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the profile kind using fprofile-instrument-use-path.
|
|
|
|
static void setPGOUseInstrumentor(CodeGenOptions &Opts,
|
2016-05-29 19:04:56 +08:00
|
|
|
const Twine &ProfileName) {
|
2016-03-03 04:59:36 +08:00
|
|
|
auto ReaderOrErr = llvm::IndexedInstrProfReader::create(ProfileName);
|
|
|
|
// In error, return silently and let Clang PGOUse report the error message.
|
2016-05-19 11:54:54 +08:00
|
|
|
if (auto E = ReaderOrErr.takeError()) {
|
|
|
|
llvm::consumeError(std::move(E));
|
2016-03-03 04:59:36 +08:00
|
|
|
Opts.setProfileUse(CodeGenOptions::ProfileClangInstr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
std::unique_ptr<llvm::IndexedInstrProfReader> PGOReader =
|
|
|
|
std::move(ReaderOrErr.get());
|
2019-03-05 04:21:31 +08:00
|
|
|
if (PGOReader->isIRLevelProfile()) {
|
|
|
|
if (PGOReader->hasCSIRLevelProfile())
|
|
|
|
Opts.setProfileUse(CodeGenOptions::ProfileCSIRInstr);
|
|
|
|
else
|
|
|
|
Opts.setProfileUse(CodeGenOptions::ProfileIRInstr);
|
|
|
|
} else
|
2016-03-03 04:59:36 +08:00
|
|
|
Opts.setProfileUse(CodeGenOptions::ProfileClangInstr);
|
|
|
|
}
|
|
|
|
|
2011-12-23 11:05:38 +08:00
|
|
|
static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
|
2014-01-07 09:19:08 +08:00
|
|
|
DiagnosticsEngine &Diags,
|
2018-04-18 00:39:25 +08:00
|
|
|
const TargetOptions &TargetOpts,
|
|
|
|
const FrontendOptions &FrontendOpts) {
|
2011-12-23 11:05:38 +08:00
|
|
|
bool Success = true;
|
2015-12-11 02:52:50 +08:00
|
|
|
llvm::Triple Triple = llvm::Triple(TargetOpts.Triple);
|
2010-12-04 09:50:36 +08:00
|
|
|
|
2014-12-17 05:57:03 +08:00
|
|
|
unsigned OptimizationLevel = getOptimizationLevel(Args, IK, Diags);
|
2013-11-18 21:23:07 +08:00
|
|
|
// TODO: This could be done in Driver
|
|
|
|
unsigned MaxOptLevel = 3;
|
2014-12-17 05:57:03 +08:00
|
|
|
if (OptimizationLevel > MaxOptLevel) {
|
|
|
|
// If the optimization level is not supported, fall back on the default
|
|
|
|
// optimization
|
2013-11-18 21:23:07 +08:00
|
|
|
Diags.Report(diag::warn_drv_optimization_value)
|
|
|
|
<< Args.getLastArg(OPT_O)->getAsString(Args) << "-O" << MaxOptLevel;
|
2014-12-17 05:57:03 +08:00
|
|
|
OptimizationLevel = MaxOptLevel;
|
2009-12-01 11:16:53 +08:00
|
|
|
}
|
2014-12-17 05:57:03 +08:00
|
|
|
Opts.OptimizationLevel = OptimizationLevel;
|
2009-12-01 11:16:53 +08:00
|
|
|
|
Cleanup the handling of noinline function attributes, -fno-inline,
-fno-inline-functions, -O0, and optnone.
These were really, really tangled together:
- We used the noinline LLVM attribute for -fno-inline
- But not for -fno-inline-functions (breaking LTO)
- But we did use it for -finline-hint-functions (yay, LTO is happy!)
- But we didn't for -O0 (LTO is sad yet again...)
- We had weird structuring of CodeGenOpts with both an inlining
enumeration and a boolean. They interacted in weird ways and
needlessly.
- A *lot* of set smashing went on with setting these, and then got worse
when we considered optnone and other inlining-effecting attributes.
- A bunch of inline affecting attributes were managed in a completely
different place from -fno-inline.
- Even with -fno-inline we failed to put the LLVM noinline attribute
onto many generated function definitions because they didn't show up
as AST-level functions.
- If you passed -O0 but -finline-functions we would run the normal
inliner pass in LLVM despite it being in the O0 pipeline, which really
doesn't make much sense.
- Lastly, we used things like '-fno-inline' to manipulate the pass
pipeline which forced the pass pipeline to be much more
parameterizable than it really needs to be. Instead we can *just* use
the optimization level to select a pipeline and control the rest via
attributes.
Sadly, this causes a bunch of churn in tests because we don't run the
optimizer in the tests and check the contents of attribute sets. It
would be awesome if attribute sets were a bit more FileCheck friendly,
but oh well.
I think this is a significant improvement and should remove the semantic
need to change what inliner pass we run in order to comply with the
requested inlining semantics by relying completely on attributes. It
also cleans up tho optnone and related handling a bit.
One unfortunate aspect of this is that for generating alwaysinline
routines like those in OpenMP we end up removing noinline and then
adding alwaysinline. I tried a bunch of other approaches, but because we
recompute function attributes from scratch and don't have a declaration
here I couldn't find anything substantially cleaner than this.
Differential Revision: https://reviews.llvm.org/D28053
llvm-svn: 290398
2016-12-23 09:24:49 +08:00
|
|
|
// At O0 we want to fully disable inlining outside of cases marked with
|
|
|
|
// 'alwaysinline' that are required for correctness.
|
|
|
|
Opts.setInlining((Opts.OptimizationLevel == 0)
|
|
|
|
? CodeGenOptions::OnlyAlwaysInlining
|
|
|
|
: CodeGenOptions::NormalInlining);
|
|
|
|
// Explicit inlining flags can disable some or all inlining even at
|
|
|
|
// optimization levels above zero.
|
|
|
|
if (Arg *InlineArg = Args.getLastArg(
|
|
|
|
options::OPT_finline_functions, options::OPT_finline_hint_functions,
|
|
|
|
options::OPT_fno_inline_functions, options::OPT_fno_inline)) {
|
|
|
|
if (Opts.OptimizationLevel > 0) {
|
|
|
|
const Option &InlineOpt = InlineArg->getOption();
|
|
|
|
if (InlineOpt.matches(options::OPT_finline_functions))
|
|
|
|
Opts.setInlining(CodeGenOptions::NormalInlining);
|
|
|
|
else if (InlineOpt.matches(options::OPT_finline_hint_functions))
|
|
|
|
Opts.setInlining(CodeGenOptions::OnlyHintInlining);
|
|
|
|
else
|
|
|
|
Opts.setInlining(CodeGenOptions::OnlyAlwaysInlining);
|
|
|
|
}
|
2016-05-25 04:40:51 +08:00
|
|
|
}
|
2009-12-01 11:16:53 +08:00
|
|
|
|
2016-12-24 04:44:01 +08:00
|
|
|
Opts.ExperimentalNewPassManager = Args.hasFlag(
|
|
|
|
OPT_fexperimental_new_pass_manager, OPT_fno_experimental_new_pass_manager,
|
2018-04-06 08:53:00 +08:00
|
|
|
/* Default */ ENABLE_EXPERIMENTAL_NEW_PASS_MANAGER);
|
2016-12-24 04:44:01 +08:00
|
|
|
|
2017-06-30 07:10:13 +08:00
|
|
|
Opts.DebugPassManager =
|
|
|
|
Args.hasFlag(OPT_fdebug_pass_manager, OPT_fno_debug_pass_manager,
|
|
|
|
/* Default */ false);
|
|
|
|
|
2015-03-18 04:03:11 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_fveclib)) {
|
|
|
|
StringRef Name = A->getValue();
|
|
|
|
if (Name == "Accelerate")
|
|
|
|
Opts.setVecLib(CodeGenOptions::Accelerate);
|
2019-06-05 09:57:57 +08:00
|
|
|
else if (Name == "MASSV")
|
|
|
|
Opts.setVecLib(CodeGenOptions::MASSV);
|
2016-07-30 00:44:24 +08:00
|
|
|
else if (Name == "SVML")
|
|
|
|
Opts.setVecLib(CodeGenOptions::SVML);
|
2015-03-18 04:03:11 +08:00
|
|
|
else if (Name == "none")
|
|
|
|
Opts.setVecLib(CodeGenOptions::NoLibrary);
|
|
|
|
else
|
|
|
|
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
|
|
|
|
}
|
|
|
|
|
2015-10-08 12:24:12 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_debug_info_kind_EQ)) {
|
2016-01-06 09:37:57 +08:00
|
|
|
unsigned Val =
|
|
|
|
llvm::StringSwitch<unsigned>(A->getValue())
|
2016-02-02 19:06:51 +08:00
|
|
|
.Case("line-tables-only", codegenoptions::DebugLineTablesOnly)
|
2018-08-31 21:56:14 +08:00
|
|
|
.Case("line-directives-only", codegenoptions::DebugDirectivesOnly)
|
2016-02-02 19:06:51 +08:00
|
|
|
.Case("limited", codegenoptions::LimitedDebugInfo)
|
|
|
|
.Case("standalone", codegenoptions::FullDebugInfo)
|
2016-01-06 09:37:57 +08:00
|
|
|
.Default(~0U);
|
|
|
|
if (Val == ~0U)
|
|
|
|
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
|
|
|
|
<< A->getValue();
|
|
|
|
else
|
2016-02-02 19:06:51 +08:00
|
|
|
Opts.setDebugInfo(static_cast<codegenoptions::DebugInfoKind>(Val));
|
2012-04-27 15:24:20 +08:00
|
|
|
}
|
2015-12-19 10:24:10 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_debugger_tuning_EQ)) {
|
2016-01-06 09:37:57 +08:00
|
|
|
unsigned Val = llvm::StringSwitch<unsigned>(A->getValue())
|
2016-02-06 07:23:25 +08:00
|
|
|
.Case("gdb", unsigned(llvm::DebuggerKind::GDB))
|
|
|
|
.Case("lldb", unsigned(llvm::DebuggerKind::LLDB))
|
|
|
|
.Case("sce", unsigned(llvm::DebuggerKind::SCE))
|
2016-01-06 09:37:57 +08:00
|
|
|
.Default(~0U);
|
|
|
|
if (Val == ~0U)
|
|
|
|
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
|
|
|
|
<< A->getValue();
|
|
|
|
else
|
2016-02-06 07:23:25 +08:00
|
|
|
Opts.setDebuggerTuning(static_cast<llvm::DebuggerKind>(Val));
|
2015-12-19 10:24:10 +08:00
|
|
|
}
|
2015-10-08 12:24:12 +08:00
|
|
|
Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 0, Diags);
|
2012-10-19 05:52:18 +08:00
|
|
|
Opts.DebugColumnInfo = Args.hasArg(OPT_dwarf_column_info);
|
2015-10-08 12:24:12 +08:00
|
|
|
Opts.EmitCodeView = Args.hasArg(OPT_gcodeview);
|
2018-11-17 02:47:41 +08:00
|
|
|
Opts.CodeViewGHash = Args.hasArg(OPT_gcodeview_ghash);
|
2017-02-10 06:07:24 +08:00
|
|
|
Opts.MacroDebugInfo = Args.hasArg(OPT_debug_info_macro);
|
2016-02-25 04:46:36 +08:00
|
|
|
Opts.WholeProgramVTables = Args.hasArg(OPT_fwhole_program_vtables);
|
2016-04-29 01:09:37 +08:00
|
|
|
Opts.LTOVisibilityPublicStd = Args.hasArg(OPT_flto_visibility_public_std);
|
2019-06-15 23:38:51 +08:00
|
|
|
Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file);
|
2019-06-15 22:07:43 +08:00
|
|
|
Opts.SplitDwarfOutput = Args.getLastArgValue(OPT_split_dwarf_output);
|
2016-08-25 02:29:58 +08:00
|
|
|
Opts.SplitDwarfInlining = !Args.hasArg(OPT_fno_split_dwarf_inlining);
|
2015-08-28 03:46:20 +08:00
|
|
|
Opts.DebugTypeExtRefs = Args.hasArg(OPT_dwarf_ext_refs);
|
2017-09-30 05:25:07 +08:00
|
|
|
Opts.DebugExplicitImport = Args.hasArg(OPT_dwarf_explicit_import);
|
2017-09-29 02:37:02 +08:00
|
|
|
Opts.DebugFwdTemplateParams = Args.hasArg(OPT_debug_forward_template_params);
|
2018-02-27 01:32:31 +08:00
|
|
|
Opts.EmbedSource = Args.hasArg(OPT_gembed_source);
|
2012-04-27 15:24:20 +08:00
|
|
|
|
2015-10-13 04:21:08 +08:00
|
|
|
for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ))
|
|
|
|
Opts.DebugPrefixMap.insert(StringRef(Arg).split('='));
|
|
|
|
|
2015-04-15 09:16:18 +08:00
|
|
|
if (const Arg *A =
|
|
|
|
Args.getLastArg(OPT_emit_llvm_uselists, OPT_no_emit_llvm_uselists))
|
|
|
|
Opts.EmitLLVMUseLists = A->getOption().getID() == OPT_emit_llvm_uselists;
|
|
|
|
|
2015-07-18 04:09:56 +08:00
|
|
|
Opts.DisableLLVMPasses = Args.hasArg(OPT_disable_llvm_passes);
|
2017-01-07 07:18:09 +08:00
|
|
|
Opts.DisableLifetimeMarkers = Args.hasArg(OPT_disable_lifetimemarkers);
|
2019-06-26 17:38:09 +08:00
|
|
|
|
|
|
|
llvm::Triple T(TargetOpts.Triple);
|
|
|
|
llvm::Triple::ArchType Arch = T.getArch();
|
|
|
|
if (Opts.OptimizationLevel > 0 &&
|
|
|
|
(Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64))
|
|
|
|
Opts.EnableDebugEntryValues = Args.hasArg(OPT_femit_debug_entry_values);
|
|
|
|
|
2017-05-29 13:38:20 +08:00
|
|
|
Opts.DisableO0ImplyOptNone = Args.hasArg(OPT_disable_O0_optnone);
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.DisableRedZone = Args.hasArg(OPT_disable_red_zone);
|
2018-10-18 22:07:02 +08:00
|
|
|
Opts.IndirectTlsSegRefs = Args.hasArg(OPT_mno_tls_direct_seg_refs);
|
2011-03-18 10:56:14 +08:00
|
|
|
Opts.ForbidGuardVariables = Args.hasArg(OPT_fforbid_guard_variables);
|
IRgen: Add a -fuse-register-sized-bitfield-access option, for testing.
- Changes bit-field access policy to try to use (aligned) register sized accesses.
The idea here is that by using larger accesses we expose more coalescing
potential to the backend when we have situations like adjacent bit-fields in the
same structure (which is common), and that the backend should be smart enough to
narrow the accesses down when no coalescing is done or when it is shown not to
be profitable.
--
$ clang -m32 -O3 -S -o - t.c
_f0: ## @f0
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
movb (%eax), %cl
andb $-128, %cl
orb $1, %cl
movb %cl, (%eax)
movb 1(%eax), %cl
andb $-128, %cl
orb $1, %cl
movb %cl, 1(%eax)
movb 2(%eax), %cl
andb $-128, %cl
orb $1, %cl
movb %cl, 2(%eax)
movb 3(%eax), %cl
andb $-128, %cl
orb $1, %cl
movb %cl, 3(%eax)
popl %ebp
ret
$ clang -m32 -O3 -S -o - t.c -Xclang -fuse-register-sized-bitfield-access
_f0: ## @f0
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
movl $-2139062144, %ecx ## imm = 0xFFFFFFFF80808080
andl (%eax), %ecx
orl $16843009, %ecx ## imm = 0x1010101
movl %ecx, (%eax)
popl %ebp
ret
--
llvm-svn: 133532
2011-06-22 02:54:46 +08:00
|
|
|
Opts.UseRegisterSizedBitfieldAccess = Args.hasArg(
|
|
|
|
OPT_fuse_register_sized_bitfield_access);
|
2013-04-25 02:09:54 +08:00
|
|
|
Opts.RelaxedAliasing = Args.hasArg(OPT_relaxed_aliasing);
|
2013-10-12 04:48:38 +08:00
|
|
|
Opts.StructPathTBAA = !Args.hasArg(OPT_no_struct_path_tbaa);
|
2017-11-20 19:16:16 +08:00
|
|
|
Opts.NewStructPathTBAA = !Args.hasArg(OPT_no_struct_path_tbaa) &&
|
|
|
|
Args.hasArg(OPT_new_struct_path_tbaa);
|
2017-10-17 00:50:27 +08:00
|
|
|
Opts.FineGrainedBitfieldAccesses =
|
|
|
|
Args.hasFlag(OPT_ffine_grained_bitfield_accesses,
|
|
|
|
OPT_fno_fine_grained_bitfield_accesses, false);
|
2010-05-21 00:54:55 +08:00
|
|
|
Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags);
|
2018-12-14 23:38:15 +08:00
|
|
|
Opts.RecordCommandLine = Args.getLastArgValue(OPT_record_command_line);
|
2018-04-05 23:29:52 +08:00
|
|
|
Opts.MergeAllConstants = Args.hasArg(OPT_fmerge_all_constants);
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.NoCommon = Args.hasArg(OPT_fno_common);
|
|
|
|
Opts.NoImplicitFloat = Args.hasArg(OPT_no_implicit_float);
|
2013-04-11 05:30:03 +08:00
|
|
|
Opts.OptimizeSize = getOptimizationLevelSize(Args);
|
2010-06-08 07:19:17 +08:00
|
|
|
Opts.SimplifyLibCalls = !(Args.hasArg(OPT_fno_builtin) ||
|
|
|
|
Args.hasArg(OPT_ffreestanding));
|
2016-01-06 22:35:46 +08:00
|
|
|
if (Opts.SimplifyLibCalls)
|
|
|
|
getAllNoBuiltinFuncValues(Args, Opts.NoBuiltinFuncs);
|
2013-08-08 16:34:35 +08:00
|
|
|
Opts.UnrollLoops =
|
|
|
|
Args.hasFlag(OPT_funroll_loops, OPT_fno_unroll_loops,
|
2016-05-04 23:26:28 +08:00
|
|
|
(Opts.OptimizationLevel > 1));
|
2013-11-18 00:03:29 +08:00
|
|
|
Opts.RerollLoops = Args.hasArg(OPT_freroll_loops);
|
2009-12-01 11:16:53 +08:00
|
|
|
|
2014-02-23 08:40:30 +08:00
|
|
|
Opts.DisableIntegratedAS = Args.hasArg(OPT_fno_integrated_as);
|
2013-04-17 02:21:19 +08:00
|
|
|
Opts.Autolink = !Args.hasArg(OPT_fno_autolink);
|
2013-11-13 20:22:39 +08:00
|
|
|
Opts.SampleProfileFile = Args.getLastArgValue(OPT_fprofile_sample_use_EQ);
|
Add -fdebug-info-for-profiling to emit more debug info for sample pgo profile collection
Summary:
SamplePGO uses profile with debug info to collect profile. Unlike the traditional debugging purpose, sample pgo needs more accurate debug info to represent the profile. We add -femit-accurate-debug-info for this purpose. It can be combined with all debugging modes (-g, -gmlt, etc). It makes sure that the following pieces of info is always emitted:
* start line of all subprograms
* linkage name of all subprograms
* standalone subprograms (functions that has neither inlined nor been inlined)
The impact on speccpu2006 binary size (size increase comparing with -g0 binary, also includes data for -g binary, which does not change with this patch):
-gmlt(orig) -gmlt(patched) -g
433.milc 4.68% 5.40% 19.73%
444.namd 8.45% 8.93% 45.99%
447.dealII 97.43% 115.21% 374.89%
450.soplex 27.75% 31.88% 126.04%
453.povray 21.81% 26.16% 92.03%
470.lbm 0.60% 0.67% 1.96%
482.sphinx3 5.77% 6.47% 26.17%
400.perlbench 17.81% 19.43% 73.08%
401.bzip2 3.73% 3.92% 12.18%
403.gcc 31.75% 34.48% 122.75%
429.mcf 0.78% 0.88% 3.89%
445.gobmk 6.08% 7.92% 42.27%
456.hmmer 10.36% 11.25% 35.23%
458.sjeng 5.08% 5.42% 14.36%
462.libquantum 1.71% 1.96% 6.36%
464.h264ref 15.61% 16.56% 43.92%
471.omnetpp 11.93% 15.84% 60.09%
473.astar 3.11% 3.69% 14.18%
483.xalancbmk 56.29% 81.63% 353.22%
geomean 15.60% 18.30% 57.81%
Debug info size change for -gmlt binary with this patch:
433.milc 13.46%
444.namd 5.35%
447.dealII 18.21%
450.soplex 14.68%
453.povray 19.65%
470.lbm 6.03%
482.sphinx3 11.21%
400.perlbench 8.91%
401.bzip2 4.41%
403.gcc 8.56%
429.mcf 8.24%
445.gobmk 29.47%
456.hmmer 8.19%
458.sjeng 6.05%
462.libquantum 11.23%
464.h264ref 5.93%
471.omnetpp 31.89%
473.astar 16.20%
483.xalancbmk 44.62%
geomean 16.83%
Reviewers: davidxl, andreadb, rob.lougher, dblaikie, echristo
Reviewed By: dblaikie, echristo
Subscribers: hfinkel, rob.lougher, andreadb, gbedwell, cfe-commits, probinson, llvm-commits, mehdi_amini
Differential Revision: https://reviews.llvm.org/D25435
llvm-svn: 292458
2017-01-19 08:44:21 +08:00
|
|
|
Opts.DebugInfoForProfiling = Args.hasFlag(
|
|
|
|
OPT_fdebug_info_for_profiling, OPT_fno_debug_info_for_profiling, false);
|
2018-08-21 04:14:08 +08:00
|
|
|
Opts.DebugNameTable = static_cast<unsigned>(
|
|
|
|
Args.hasArg(OPT_ggnu_pubnames)
|
|
|
|
? llvm::DICompileUnit::DebugNameTableKind::GNU
|
|
|
|
: Args.hasArg(OPT_gpubnames)
|
|
|
|
? llvm::DICompileUnit::DebugNameTableKind::Default
|
|
|
|
: llvm::DICompileUnit::DebugNameTableKind::None);
|
2018-11-14 04:08:13 +08:00
|
|
|
Opts.DebugRangesBaseAddress = Args.hasArg(OPT_fdebug_ranges_base_address);
|
2016-02-05 02:39:09 +08:00
|
|
|
|
2016-03-03 04:59:36 +08:00
|
|
|
setPGOInstrumentor(Opts, Args, Diags);
|
|
|
|
Opts.InstrProfileOutput =
|
|
|
|
Args.getLastArgValue(OPT_fprofile_instrument_path_EQ);
|
|
|
|
Opts.ProfileInstrumentUsePath =
|
|
|
|
Args.getLastArgValue(OPT_fprofile_instrument_use_path_EQ);
|
|
|
|
if (!Opts.ProfileInstrumentUsePath.empty())
|
|
|
|
setPGOUseInstrumentor(Opts, Opts.ProfileInstrumentUsePath);
|
2018-10-11 07:13:35 +08:00
|
|
|
Opts.ProfileRemappingFile =
|
|
|
|
Args.getLastArgValue(OPT_fprofile_remapping_file_EQ);
|
|
|
|
if (!Opts.ProfileRemappingFile.empty() && !Opts.ExperimentalNewPassManager) {
|
|
|
|
Diags.Report(diag::err_drv_argument_only_allowed_with)
|
|
|
|
<< Args.getLastArg(OPT_fprofile_remapping_file_EQ)->getAsString(Args)
|
|
|
|
<< "-fexperimental-new-pass-manager";
|
|
|
|
}
|
2016-02-05 02:39:09 +08:00
|
|
|
|
2015-08-06 07:27:40 +08:00
|
|
|
Opts.CoverageMapping =
|
|
|
|
Args.hasFlag(OPT_fcoverage_mapping, OPT_fno_coverage_mapping, false);
|
2014-08-09 07:41:24 +08:00
|
|
|
Opts.DumpCoverageMapping = Args.hasArg(OPT_dump_coverage_mapping);
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.AsmVerbose = Args.hasArg(OPT_masm_verbose);
|
2016-07-28 03:57:40 +08:00
|
|
|
Opts.PreserveAsmComments = !Args.hasArg(OPT_fno_preserve_as_comments);
|
2016-04-08 05:46:12 +08:00
|
|
|
Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new);
|
2011-06-16 07:02:42 +08:00
|
|
|
Opts.ObjCAutoRefCountExceptions = Args.hasArg(OPT_fobjc_arc_exceptions);
|
2010-03-20 12:15:41 +08:00
|
|
|
Opts.CXAAtExit = !Args.hasArg(OPT_fno_use_cxa_atexit);
|
2018-04-18 02:41:52 +08:00
|
|
|
Opts.RegisterGlobalDtorsWithAtExit =
|
|
|
|
Args.hasArg(OPT_fregister_global_dtors_with_atexit);
|
2010-03-20 12:15:41 +08:00
|
|
|
Opts.CXXCtorDtorAliases = Args.hasArg(OPT_mconstructor_aliases);
|
2018-10-09 06:25:20 +08:00
|
|
|
Opts.CodeModel = TargetOpts.CodeModel;
|
2010-05-21 00:54:55 +08:00
|
|
|
Opts.DebugPass = Args.getLastArgValue(OPT_mdebug_pass);
|
2019-07-21 06:50:50 +08:00
|
|
|
|
|
|
|
// Handle -mframe-pointer option.
|
|
|
|
if (Arg *A = Args.getLastArg(OPT_mframe_pointer_EQ)) {
|
|
|
|
CodeGenOptions::FramePointerKind FP;
|
|
|
|
StringRef Name = A->getValue();
|
|
|
|
bool ValidFP = true;
|
|
|
|
if (Name == "none")
|
|
|
|
FP = CodeGenOptions::FramePointerKind::None;
|
|
|
|
else if (Name == "non-leaf")
|
|
|
|
FP = CodeGenOptions::FramePointerKind::NonLeaf;
|
|
|
|
else if (Name == "all")
|
|
|
|
FP = CodeGenOptions::FramePointerKind::All;
|
|
|
|
else {
|
|
|
|
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
|
|
|
|
Success = false;
|
|
|
|
ValidFP = false;
|
|
|
|
}
|
|
|
|
if (ValidFP)
|
|
|
|
Opts.setFramePointer(FP);
|
|
|
|
}
|
|
|
|
|
|
|
|
// -pg may override -mframe-pointer
|
|
|
|
// TODO: This should be merged into getFramePointerKind in Clang.cpp.
|
|
|
|
if (Args.hasArg(OPT_pg))
|
|
|
|
Opts.setFramePointer(CodeGenOptions::FramePointerKind::All);
|
|
|
|
|
2013-06-22 05:15:32 +08:00
|
|
|
Opts.DisableFree = Args.hasArg(OPT_disable_free);
|
2016-03-14 21:23:58 +08:00
|
|
|
Opts.DiscardValueNames = Args.hasArg(OPT_discard_value_names);
|
2012-01-23 16:29:12 +08:00
|
|
|
Opts.DisableTailCalls = Args.hasArg(OPT_mdisable_tail_calls);
|
2018-03-02 09:53:15 +08:00
|
|
|
Opts.NoEscapingBlockTailCalls =
|
|
|
|
Args.hasArg(OPT_fno_escaping_block_tail_calls);
|
2010-05-21 00:54:55 +08:00
|
|
|
Opts.FloatABI = Args.getLastArgValue(OPT_mfloat_abi);
|
2017-03-27 18:38:01 +08:00
|
|
|
Opts.LessPreciseFPMAD = Args.hasArg(OPT_cl_mad_enable) ||
|
|
|
|
Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
|
|
|
|
Args.hasArg(OPT_cl_fast_relaxed_math);
|
2010-05-21 00:54:55 +08:00
|
|
|
Opts.LimitFloatPrecision = Args.getLastArgValue(OPT_mlimit_float_precision);
|
2011-12-10 07:41:18 +08:00
|
|
|
Opts.NoInfsFPMath = (Args.hasArg(OPT_menable_no_infinities) ||
|
2014-12-11 00:41:14 +08:00
|
|
|
Args.hasArg(OPT_cl_finite_math_only) ||
|
2011-12-10 07:41:18 +08:00
|
|
|
Args.hasArg(OPT_cl_fast_relaxed_math));
|
|
|
|
Opts.NoNaNsFPMath = (Args.hasArg(OPT_menable_no_nans) ||
|
2014-12-11 00:41:14 +08:00
|
|
|
Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
|
|
|
|
Args.hasArg(OPT_cl_finite_math_only) ||
|
2011-12-10 07:41:18 +08:00
|
|
|
Args.hasArg(OPT_cl_fast_relaxed_math));
|
2016-07-09 04:28:29 +08:00
|
|
|
Opts.NoSignedZeros = (Args.hasArg(OPT_fno_signed_zeros) ||
|
2017-03-27 18:38:01 +08:00
|
|
|
Args.hasArg(OPT_cl_no_signed_zeros) ||
|
|
|
|
Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
|
|
|
|
Args.hasArg(OPT_cl_fast_relaxed_math));
|
[Driver, CodeGen] pass through and apply -fassociative-math
There are 2 parts to getting the -fassociative-math command-line flag translated to LLVM FMF:
1. In the driver/frontend, we accept the flag and its 'no' inverse and deal with the
interactions with other flags like -ffast-math -fno-signed-zeros -fno-trapping-math.
This was mostly already done - we just need to translate the flag as a codegen option.
The test file is complicated because there are many potential combinations of flags here.
Note that we are matching gcc's behavior that requires 'nsz' and no-trapping-math.
2. In codegen, we map the codegen option to FMF in the IR builder. This is simple code and
corresponding test.
For the motivating example from PR27372:
float foo(float a, float x) { return ((a + x) - x); }
$ ./clang -O2 27372.c -S -o - -ffast-math -fno-associative-math -emit-llvm | egrep 'fadd|fsub'
%add = fadd nnan ninf nsz arcp contract float %0, %1
%sub = fsub nnan ninf nsz arcp contract float %add, %2
So 'reassoc' is off as expected (and so is the new 'afn' but that's a different patch).
This case now works as expected end-to-end although the underlying logic is still wrong:
$ ./clang -O2 27372.c -S -o - -ffast-math -fno-associative-math | grep xmm
addss %xmm1, %xmm0
subss %xmm1, %xmm0
We're not done because the case where 'reassoc' is set is ignored by optimizer passes. Example:
$ ./clang -O2 27372.c -S -o - -fassociative-math -fno-signed-zeros -fno-trapping-math -emit-llvm | grep fadd
%add = fadd reassoc float %0, %1
$ ./clang -O2 27372.c -S -o - -fassociative-math -fno-signed-zeros -fno-trapping-math | grep xmm
addss %xmm1, %xmm0
subss %xmm1, %xmm0
Differential Revision: https://reviews.llvm.org/D39812
llvm-svn: 320920
2017-12-17 00:11:17 +08:00
|
|
|
Opts.Reassociate = Args.hasArg(OPT_mreassociate);
|
2018-07-21 10:02:22 +08:00
|
|
|
Opts.FlushDenorm = Args.hasArg(OPT_cl_denorms_are_zero) ||
|
|
|
|
(Args.hasArg(OPT_fcuda_is_device) &&
|
|
|
|
Args.hasArg(OPT_fcuda_flush_denormals_to_zero));
|
2016-08-10 04:10:18 +08:00
|
|
|
Opts.CorrectlyRoundedDivSqrt =
|
|
|
|
Args.hasArg(OPT_cl_fp32_correctly_rounded_divide_sqrt);
|
[OpenCL] Add '-cl-uniform-work-group-size' compile option
Summary:
OpenCL 2.0 specification defines '-cl-uniform-work-group-size' option,
which requires that the global work-size be a multiple of the work-group
size specified to clEnqueueNDRangeKernel and allows optimizations that
are made possible by this restriction.
The patch introduces the support of this option.
To keep information about whether an OpenCL kernel has uniform work
group size or not, clang generates 'uniform-work-group-size' function
attribute for every kernel:
- "uniform-work-group-size"="true" for OpenCL 1.2 and lower,
- "uniform-work-group-size"="true" for OpenCL 2.0 and higher if
'-cl-uniform-work-group-size' option was specified,
- "uniform-work-group-size"="false" for OpenCL 2.0 and higher if no
'-cl-uniform-work-group-size' options was specified.
If the function is not an OpenCL kernel, 'uniform-work-group-size'
attribute isn't generated.
Patch by: krisb
Reviewers: yaxunl, Anastasia, b-sumner
Reviewed By: yaxunl, Anastasia
Subscribers: nhaehnle, yaxunl, Anastasia, cfe-commits
Differential Revision: https://reviews.llvm.org/D43570
llvm-svn: 325771
2018-02-22 19:54:14 +08:00
|
|
|
Opts.UniformWGSize =
|
|
|
|
Args.hasArg(OPT_cl_uniform_work_group_size);
|
2017-11-21 01:09:22 +08:00
|
|
|
Opts.Reciprocals = Args.getAllArgValues(OPT_mrecip_EQ);
|
2015-04-09 23:03:23 +08:00
|
|
|
Opts.ReciprocalMath = Args.hasArg(OPT_freciprocal_math);
|
2016-08-30 16:09:45 +08:00
|
|
|
Opts.NoTrappingMath = Args.hasArg(OPT_fno_trapping_math);
|
2018-05-01 02:19:03 +08:00
|
|
|
Opts.StrictFloatCastOverflow =
|
|
|
|
!Args.hasArg(OPT_fno_strict_float_cast_overflow);
|
2018-04-27 22:22:48 +08:00
|
|
|
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss);
|
2013-06-15 01:17:23 +08:00
|
|
|
Opts.NumRegisterParameters = getLastArgIntValue(Args, OPT_mregparm, 0, Diags);
|
2011-06-21 08:14:18 +08:00
|
|
|
Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack);
|
2014-08-27 02:40:25 +08:00
|
|
|
Opts.FatalWarnings = Args.hasArg(OPT_massembler_fatal_warnings);
|
2019-08-09 03:19:20 +08:00
|
|
|
Opts.NoWarn = Args.hasArg(OPT_massembler_no_warn);
|
2013-04-04 14:29:47 +08:00
|
|
|
Opts.EnableSegmentedStacks = Args.hasArg(OPT_split_stacks);
|
2010-05-27 13:39:39 +08:00
|
|
|
Opts.RelaxAll = Args.hasArg(OPT_mrelax_all);
|
2015-12-22 06:09:34 +08:00
|
|
|
Opts.IncrementalLinkerCompatible =
|
|
|
|
Args.hasArg(OPT_mincremental_linker_compatible);
|
2016-10-20 04:24:06 +08:00
|
|
|
Opts.PIECopyRelocations =
|
|
|
|
Args.hasArg(OPT_mpie_copy_relocations);
|
2017-11-08 03:37:51 +08:00
|
|
|
Opts.NoPLT = Args.hasArg(OPT_fno_plt);
|
2011-03-29 06:49:28 +08:00
|
|
|
Opts.SaveTempLabels = Args.hasArg(OPT_msave_temp_labels);
|
2011-10-18 07:05:52 +08:00
|
|
|
Opts.NoDwarfDirectoryAsm = Args.hasArg(OPT_fno_dwarf_directory_asm);
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.SoftFloat = Args.hasArg(OPT_msoft_float);
|
2012-03-28 07:58:37 +08:00
|
|
|
Opts.StrictEnums = Args.hasArg(OPT_fstrict_enums);
|
2017-01-04 21:40:34 +08:00
|
|
|
Opts.StrictReturn = !Args.hasArg(OPT_fno_strict_return);
|
2015-09-16 05:46:47 +08:00
|
|
|
Opts.StrictVTablePointers = Args.hasArg(OPT_fstrict_vtable_pointers);
|
2018-06-13 21:55:42 +08:00
|
|
|
Opts.ForceEmitVTables = Args.hasArg(OPT_fforce_emit_vtables);
|
2012-01-02 22:19:45 +08:00
|
|
|
Opts.UnsafeFPMath = Args.hasArg(OPT_menable_unsafe_fp_math) ||
|
|
|
|
Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
|
2010-12-04 09:51:23 +08:00
|
|
|
Args.hasArg(OPT_cl_fast_relaxed_math);
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.UnwindTables = Args.hasArg(OPT_munwind_tables);
|
2017-04-02 05:07:07 +08:00
|
|
|
Opts.RelocationModel = getRelocModel(Args, Diags);
|
2014-10-04 05:57:44 +08:00
|
|
|
Opts.ThreadModel = Args.getLastArgValue(OPT_mthread_model, "posix");
|
|
|
|
if (Opts.ThreadModel != "posix" && Opts.ThreadModel != "single")
|
|
|
|
Diags.Report(diag::err_drv_invalid_value)
|
|
|
|
<< Args.getLastArg(OPT_mthread_model)->getAsString(Args)
|
|
|
|
<< Opts.ThreadModel;
|
2012-02-03 14:27:22 +08:00
|
|
|
Opts.TrapFuncName = Args.getLastArgValue(OPT_ftrap_function_EQ);
|
2012-06-19 09:26:10 +08:00
|
|
|
Opts.UseInitArray = Args.hasArg(OPT_fuse_init_array);
|
2009-12-01 11:16:53 +08:00
|
|
|
|
2013-10-11 11:35:10 +08:00
|
|
|
Opts.FunctionSections = Args.hasFlag(OPT_ffunction_sections,
|
|
|
|
OPT_fno_function_sections, false);
|
|
|
|
Opts.DataSections = Args.hasFlag(OPT_fdata_sections,
|
|
|
|
OPT_fno_data_sections, false);
|
2018-01-08 21:42:26 +08:00
|
|
|
Opts.StackSizeSection =
|
|
|
|
Args.hasFlag(OPT_fstack_size_section, OPT_fno_stack_size_section, false);
|
2015-02-21 02:08:57 +08:00
|
|
|
Opts.UniqueSectionNames = Args.hasFlag(OPT_funique_section_names,
|
|
|
|
OPT_fno_unique_section_names, true);
|
|
|
|
|
2014-10-24 08:49:29 +08:00
|
|
|
Opts.MergeFunctions = Args.hasArg(OPT_fmerge_functions);
|
2010-04-13 08:38:24 +08:00
|
|
|
|
2016-04-06 01:50:43 +08:00
|
|
|
Opts.NoUseJumpTables = Args.hasArg(OPT_fno_jump_tables);
|
|
|
|
|
[clang]: Add support for "-fno-delete-null-pointer-checks"
Summary:
Support for this option is needed for building Linux kernel.
This is a very frequently requested feature by kernel developers.
More details : https://lkml.org/lkml/2018/4/4/601
GCC option description for -fdelete-null-pointer-checks:
This Assume that programs cannot safely dereference null pointers,
and that no code or data element resides at address zero.
-fno-delete-null-pointer-checks is the inverse of this implying that
null pointer dereferencing is not undefined.
This feature is implemented in as the function attribute
"null-pointer-is-valid"="true".
This CL only adds the attribute on the function.
It also strips "nonnull" attributes from function arguments but
keeps the related warnings unchanged.
Corresponding LLVM change rL336613 already updated the
optimizations to not treat null pointer dereferencing
as undefined if the attribute is present.
Reviewers: t.p.northover, efriedma, jyknight, chandlerc, rnk, srhines, void, george.burgess.iv
Reviewed By: jyknight
Subscribers: drinkcat, xbolva00, cfe-commits
Differential Revision: https://reviews.llvm.org/D47894
llvm-svn: 337433
2018-07-19 08:44:52 +08:00
|
|
|
Opts.NullPointerIsValid = Args.hasArg(OPT_fno_delete_null_pointer_checks);
|
|
|
|
|
2017-08-25 05:37:33 +08:00
|
|
|
Opts.ProfileSampleAccurate = Args.hasArg(OPT_fprofile_sample_accurate);
|
|
|
|
|
2015-10-16 04:35:53 +08:00
|
|
|
Opts.PrepareForLTO = Args.hasArg(OPT_flto, OPT_flto_EQ);
|
2018-06-23 04:23:21 +08:00
|
|
|
Opts.PrepareForThinLTO = false;
|
2017-06-14 23:37:11 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_flto_EQ)) {
|
|
|
|
StringRef S = A->getValue();
|
|
|
|
if (S == "thin")
|
2018-06-23 04:23:21 +08:00
|
|
|
Opts.PrepareForThinLTO = true;
|
2017-06-14 23:37:11 +08:00
|
|
|
else if (S != "full")
|
|
|
|
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << S;
|
|
|
|
}
|
2017-01-19 07:55:27 +08:00
|
|
|
Opts.LTOUnit = Args.hasFlag(OPT_flto_unit, OPT_fno_lto_unit, false);
|
2019-01-12 02:32:07 +08:00
|
|
|
Opts.EnableSplitLTOUnit = Args.hasArg(OPT_fsplit_lto_unit);
|
2015-12-08 03:21:34 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_fthinlto_index_EQ)) {
|
2019-08-05 21:59:26 +08:00
|
|
|
if (IK.getLanguage() != Language::LLVM_IR)
|
2015-12-08 03:21:34 +08:00
|
|
|
Diags.Report(diag::err_drv_argument_only_allowed_with)
|
|
|
|
<< A->getAsString(Args) << "-x ir";
|
|
|
|
Opts.ThinLTOIndexFile = Args.getLastArgValue(OPT_fthinlto_index_EQ);
|
|
|
|
}
|
2018-04-18 00:39:25 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_save_temps_EQ))
|
|
|
|
Opts.SaveTempsFilePrefix =
|
|
|
|
llvm::StringSwitch<std::string>(A->getValue())
|
|
|
|
.Case("obj", FrontendOpts.OutputFile)
|
|
|
|
.Default(llvm::sys::path::filename(FrontendOpts.OutputFile).str());
|
|
|
|
|
2017-03-24 03:47:49 +08:00
|
|
|
Opts.ThinLinkBitcodeFile = Args.getLastArgValue(OPT_fthin_link_bitcode_EQ);
|
2015-07-07 00:23:00 +08:00
|
|
|
|
2015-02-14 09:35:12 +08:00
|
|
|
Opts.MSVolatile = Args.hasArg(OPT_fms_volatile);
|
|
|
|
|
2013-06-25 09:49:44 +08:00
|
|
|
Opts.VectorizeLoop = Args.hasArg(OPT_vectorize_loops);
|
|
|
|
Opts.VectorizeSLP = Args.hasArg(OPT_vectorize_slp);
|
|
|
|
|
2017-12-12 05:09:19 +08:00
|
|
|
Opts.PreferVectorWidth = Args.getLastArgValue(OPT_mprefer_vector_width_EQ);
|
|
|
|
|
2010-05-21 00:54:55 +08:00
|
|
|
Opts.MainFileName = Args.getLastArgValue(OPT_main_file_name);
|
2010-02-13 07:47:27 +08:00
|
|
|
Opts.VerifyModule = !Args.hasArg(OPT_disable_llvm_verifier);
|
2010-04-25 01:56:46 +08:00
|
|
|
|
2018-01-10 07:49:30 +08:00
|
|
|
Opts.ControlFlowGuard = Args.hasArg(OPT_cfguard);
|
|
|
|
|
2013-03-20 09:38:16 +08:00
|
|
|
Opts.DisableGCov = Args.hasArg(OPT_test_coverage);
|
2011-04-22 07:44:07 +08:00
|
|
|
Opts.EmitGcovArcs = Args.hasArg(OPT_femit_coverage_data);
|
|
|
|
Opts.EmitGcovNotes = Args.hasArg(OPT_femit_coverage_notes);
|
2013-03-07 16:28:53 +08:00
|
|
|
if (Opts.EmitGcovArcs || Opts.EmitGcovNotes) {
|
2016-09-01 07:04:32 +08:00
|
|
|
Opts.CoverageDataFile = Args.getLastArgValue(OPT_coverage_data_file);
|
|
|
|
Opts.CoverageNotesFile = Args.getLastArgValue(OPT_coverage_notes_file);
|
2013-03-07 16:28:53 +08:00
|
|
|
Opts.CoverageExtraChecksum = Args.hasArg(OPT_coverage_cfg_checksum);
|
2013-03-20 10:14:38 +08:00
|
|
|
Opts.CoverageNoFunctionNamesInData =
|
|
|
|
Args.hasArg(OPT_coverage_no_function_names_in_data);
|
2018-11-18 03:41:39 +08:00
|
|
|
Opts.ProfileFilterFiles =
|
|
|
|
Args.getLastArgValue(OPT_fprofile_filter_files_EQ);
|
|
|
|
Opts.ProfileExcludeFiles =
|
|
|
|
Args.getLastArgValue(OPT_fprofile_exclude_files_EQ);
|
2015-03-17 07:52:21 +08:00
|
|
|
Opts.CoverageExitBlockBeforeBody =
|
|
|
|
Args.hasArg(OPT_coverage_exit_block_before_body);
|
2013-03-07 16:28:53 +08:00
|
|
|
if (Args.hasArg(OPT_coverage_version_EQ)) {
|
|
|
|
StringRef CoverageVersion = Args.getLastArgValue(OPT_coverage_version_EQ);
|
|
|
|
if (CoverageVersion.size() != 4) {
|
|
|
|
Diags.Report(diag::err_drv_invalid_value)
|
|
|
|
<< Args.getLastArg(OPT_coverage_version_EQ)->getAsString(Args)
|
|
|
|
<< CoverageVersion;
|
|
|
|
} else {
|
2013-03-14 13:14:01 +08:00
|
|
|
memcpy(Opts.CoverageVersion, CoverageVersion.data(), 4);
|
2013-03-07 16:28:53 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-07-20 16:19:20 +08:00
|
|
|
// Handle -fembed-bitcode option.
|
2016-05-12 00:26:03 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_fembed_bitcode_EQ)) {
|
|
|
|
StringRef Name = A->getValue();
|
|
|
|
unsigned Model = llvm::StringSwitch<unsigned>(Name)
|
|
|
|
.Case("off", CodeGenOptions::Embed_Off)
|
|
|
|
.Case("all", CodeGenOptions::Embed_All)
|
|
|
|
.Case("bitcode", CodeGenOptions::Embed_Bitcode)
|
|
|
|
.Case("marker", CodeGenOptions::Embed_Marker)
|
|
|
|
.Default(~0U);
|
|
|
|
if (Model == ~0U) {
|
|
|
|
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
|
|
|
|
Success = false;
|
|
|
|
} else
|
|
|
|
Opts.setEmbedBitcode(
|
|
|
|
static_cast<CodeGenOptions::EmbedBitcodeKind>(Model));
|
|
|
|
}
|
|
|
|
// FIXME: For backend options that are not yet recorded as function
|
|
|
|
// attributes in the IR, keep track of them so we can embed them in a
|
|
|
|
// separate data section and use them when building the bitcode.
|
|
|
|
if (Opts.getEmbedBitcode() == CodeGenOptions::Embed_All) {
|
|
|
|
for (const auto &A : Args) {
|
|
|
|
// Do not encode output and input.
|
|
|
|
if (A->getOption().getID() == options::OPT_o ||
|
|
|
|
A->getOption().getID() == options::OPT_INPUT ||
|
|
|
|
A->getOption().getID() == options::OPT_x ||
|
|
|
|
A->getOption().getID() == options::OPT_fembed_bitcode ||
|
|
|
|
(A->getOption().getGroup().isValid() &&
|
|
|
|
A->getOption().getGroup().getID() == options::OPT_W_Group))
|
|
|
|
continue;
|
|
|
|
ArgStringList ASL;
|
|
|
|
A->render(Args, ASL);
|
|
|
|
for (const auto &arg : ASL) {
|
|
|
|
StringRef ArgStr(arg);
|
|
|
|
Opts.CmdArgs.insert(Opts.CmdArgs.end(), ArgStr.begin(), ArgStr.end());
|
Misc typos fixes in ./lib folder
Summary: Found via `codespell -q 3 -I ../clang-whitelist.txt -L uint,importd,crasher,gonna,cant,ue,ons,orign,ned`
Reviewers: teemperor
Reviewed By: teemperor
Subscribers: teemperor, jholewinski, jvesely, nhaehnle, whisperity, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D55475
llvm-svn: 348755
2018-12-10 20:37:46 +08:00
|
|
|
// using \00 to separate each commandline options.
|
2016-05-12 00:26:03 +08:00
|
|
|
Opts.CmdArgs.push_back('\0');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-03-07 16:28:53 +08:00
|
|
|
|
2017-04-05 00:40:25 +08:00
|
|
|
Opts.PreserveVec3Type = Args.hasArg(OPT_fpreserve_vec3_type);
|
2013-03-07 16:28:53 +08:00
|
|
|
Opts.InstrumentFunctions = Args.hasArg(OPT_finstrument_functions);
|
2017-11-15 05:13:27 +08:00
|
|
|
Opts.InstrumentFunctionsAfterInlining =
|
|
|
|
Args.hasArg(OPT_finstrument_functions_after_inlining);
|
2017-11-22 01:30:34 +08:00
|
|
|
Opts.InstrumentFunctionEntryBare =
|
|
|
|
Args.hasArg(OPT_finstrument_function_entry_bare);
|
2018-04-13 10:31:58 +08:00
|
|
|
|
|
|
|
Opts.XRayInstrumentFunctions =
|
|
|
|
Args.hasArg(OPT_fxray_instrument);
|
2017-11-30 08:04:54 +08:00
|
|
|
Opts.XRayAlwaysEmitCustomEvents =
|
|
|
|
Args.hasArg(OPT_fxray_always_emit_customevents);
|
2018-04-18 05:32:43 +08:00
|
|
|
Opts.XRayAlwaysEmitTypedEvents =
|
|
|
|
Args.hasArg(OPT_fxray_always_emit_typedevents);
|
2016-07-14 06:32:15 +08:00
|
|
|
Opts.XRayInstructionThreshold =
|
2017-03-31 06:46:45 +08:00
|
|
|
getLastArgIntValue(Args, OPT_fxray_instruction_threshold_EQ, 200, Diags);
|
2018-04-13 10:31:58 +08:00
|
|
|
|
|
|
|
auto XRayInstrBundles =
|
|
|
|
Args.getAllArgValues(OPT_fxray_instrumentation_bundle);
|
|
|
|
if (XRayInstrBundles.empty())
|
|
|
|
Opts.XRayInstrumentationBundle.Mask = XRayInstrKind::All;
|
|
|
|
else
|
|
|
|
for (const auto &A : XRayInstrBundles)
|
|
|
|
parseXRayInstrumentationBundle("-fxray-instrumentation-bundle=", A, Args,
|
|
|
|
Diags, Opts.XRayInstrumentationBundle);
|
|
|
|
|
2013-03-07 16:28:53 +08:00
|
|
|
Opts.InstrumentForProfiling = Args.hasArg(OPT_pg);
|
2017-02-01 01:00:35 +08:00
|
|
|
Opts.CallFEntry = Args.hasArg(OPT_mfentry);
|
2013-03-07 16:28:53 +08:00
|
|
|
Opts.EmitOpenCLArgMetadata = Args.hasArg(OPT_cl_kernel_arg_info);
|
2017-06-23 23:34:16 +08:00
|
|
|
|
2018-01-09 16:53:59 +08:00
|
|
|
if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) {
|
|
|
|
StringRef Name = A->getValue();
|
|
|
|
if (Name == "full") {
|
|
|
|
Opts.CFProtectionReturn = 1;
|
|
|
|
Opts.CFProtectionBranch = 1;
|
|
|
|
} else if (Name == "return")
|
|
|
|
Opts.CFProtectionReturn = 1;
|
|
|
|
else if (Name == "branch")
|
|
|
|
Opts.CFProtectionBranch = 1;
|
|
|
|
else if (Name != "none") {
|
|
|
|
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
|
|
|
|
Success = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-23 23:34:16 +08:00
|
|
|
if (const Arg *A = Args.getLastArg(OPT_compress_debug_sections,
|
|
|
|
OPT_compress_debug_sections_EQ)) {
|
|
|
|
if (A->getOption().getID() == OPT_compress_debug_sections) {
|
2019-05-15 03:40:42 +08:00
|
|
|
// TODO: be more clever about the compression type auto-detection
|
|
|
|
Opts.setCompressDebugSections(llvm::DebugCompressionType::GNU);
|
2017-06-23 23:34:16 +08:00
|
|
|
} else {
|
|
|
|
auto DCT = llvm::StringSwitch<llvm::DebugCompressionType>(A->getValue())
|
|
|
|
.Case("none", llvm::DebugCompressionType::None)
|
|
|
|
.Case("zlib", llvm::DebugCompressionType::Z)
|
|
|
|
.Case("zlib-gnu", llvm::DebugCompressionType::GNU)
|
|
|
|
.Default(llvm::DebugCompressionType::None);
|
|
|
|
Opts.setCompressDebugSections(DCT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-29 10:01:14 +08:00
|
|
|
Opts.RelaxELFRelocations = Args.hasArg(OPT_mrelax_relocations);
|
2011-10-21 10:32:14 +08:00
|
|
|
Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir);
|
2018-03-27 05:45:04 +08:00
|
|
|
for (auto *A :
|
2018-08-21 02:16:48 +08:00
|
|
|
Args.filtered(OPT_mlink_bitcode_file, OPT_mlink_builtin_bitcode)) {
|
[CodeGen] [CUDA] Add the ability set default attrs on functions in linked modules.
Summary:
Now when you ask clang to link in a bitcode module, you can tell it to
set attributes on that module's functions to match what we would have
set if we'd emitted those functions ourselves.
This is particularly important for fast-math attributes in CUDA
compilations.
Each CUDA compilation links in libdevice, a bitcode library provided by
nvidia as part of the CUDA distribution. Without this patch, if we have
a user-function F that is compiled with -ffast-math that calls a
function G from libdevice, F will have the unsafe-fp-math=true (etc.)
attributes, but G will have no attributes.
Since F calls G, the inliner will merge G's attributes into F's. It
considers the lack of an unsafe-fp-math=true attribute on G to be
tantamount to unsafe-fp-math=false, so it "merges" these by setting
unsafe-fp-math=false on F.
This then continues up the call graph, until every function that
(transitively) calls something in libdevice gets unsafe-fp-math=false
set, thus disabling fastmath in almost all CUDA code.
Reviewers: echristo
Subscribers: hfinkel, llvm-commits, mehdi_amini
Differential Revision: https://reviews.llvm.org/D28538
llvm-svn: 293097
2017-01-26 05:29:48 +08:00
|
|
|
CodeGenOptions::BitcodeFileToLink F;
|
|
|
|
F.Filename = A->getValue();
|
2018-08-21 02:16:48 +08:00
|
|
|
if (A->getOption().matches(OPT_mlink_builtin_bitcode)) {
|
2017-03-14 02:08:11 +08:00
|
|
|
F.LinkFlags = llvm::Linker::Flags::LinkOnlyNeeded;
|
[CodeGen] [CUDA] Add the ability set default attrs on functions in linked modules.
Summary:
Now when you ask clang to link in a bitcode module, you can tell it to
set attributes on that module's functions to match what we would have
set if we'd emitted those functions ourselves.
This is particularly important for fast-math attributes in CUDA
compilations.
Each CUDA compilation links in libdevice, a bitcode library provided by
nvidia as part of the CUDA distribution. Without this patch, if we have
a user-function F that is compiled with -ffast-math that calls a
function G from libdevice, F will have the unsafe-fp-math=true (etc.)
attributes, but G will have no attributes.
Since F calls G, the inliner will merge G's attributes into F's. It
considers the lack of an unsafe-fp-math=true attribute on G to be
tantamount to unsafe-fp-math=false, so it "merges" these by setting
unsafe-fp-math=false on F.
This then continues up the call graph, until every function that
(transitively) calls something in libdevice gets unsafe-fp-math=false
set, thus disabling fastmath in almost all CUDA code.
Reviewers: echristo
Subscribers: hfinkel, llvm-commits, mehdi_amini
Differential Revision: https://reviews.llvm.org/D28538
llvm-svn: 293097
2017-01-26 05:29:48 +08:00
|
|
|
// When linking CUDA bitcode, propagate function attributes so that
|
|
|
|
// e.g. libdevice gets fast-math attrs if we're building with fast-math.
|
|
|
|
F.PropagateAttrs = true;
|
2017-03-14 02:08:11 +08:00
|
|
|
F.Internalize = true;
|
[CodeGen] [CUDA] Add the ability set default attrs on functions in linked modules.
Summary:
Now when you ask clang to link in a bitcode module, you can tell it to
set attributes on that module's functions to match what we would have
set if we'd emitted those functions ourselves.
This is particularly important for fast-math attributes in CUDA
compilations.
Each CUDA compilation links in libdevice, a bitcode library provided by
nvidia as part of the CUDA distribution. Without this patch, if we have
a user-function F that is compiled with -ffast-math that calls a
function G from libdevice, F will have the unsafe-fp-math=true (etc.)
attributes, but G will have no attributes.
Since F calls G, the inliner will merge G's attributes into F's. It
considers the lack of an unsafe-fp-math=true attribute on G to be
tantamount to unsafe-fp-math=false, so it "merges" these by setting
unsafe-fp-math=false on F.
This then continues up the call graph, until every function that
(transitively) calls something in libdevice gets unsafe-fp-math=false
set, thus disabling fastmath in almost all CUDA code.
Reviewers: echristo
Subscribers: hfinkel, llvm-commits, mehdi_amini
Differential Revision: https://reviews.llvm.org/D28538
llvm-svn: 293097
2017-01-26 05:29:48 +08:00
|
|
|
}
|
|
|
|
Opts.LinkBitcodeFiles.push_back(F);
|
2015-10-28 01:56:59 +08:00
|
|
|
}
|
2015-05-08 02:31:29 +08:00
|
|
|
Opts.SanitizeCoverageType =
|
|
|
|
getLastArgIntValue(Args, OPT_fsanitize_coverage_type, 0, Diags);
|
|
|
|
Opts.SanitizeCoverageIndirectCalls =
|
|
|
|
Args.hasArg(OPT_fsanitize_coverage_indirect_calls);
|
|
|
|
Opts.SanitizeCoverageTraceBB = Args.hasArg(OPT_fsanitize_coverage_trace_bb);
|
|
|
|
Opts.SanitizeCoverageTraceCmp = Args.hasArg(OPT_fsanitize_coverage_trace_cmp);
|
2016-08-30 09:27:03 +08:00
|
|
|
Opts.SanitizeCoverageTraceDiv = Args.hasArg(OPT_fsanitize_coverage_trace_div);
|
|
|
|
Opts.SanitizeCoverageTraceGep = Args.hasArg(OPT_fsanitize_coverage_trace_gep);
|
2015-05-08 02:31:29 +08:00
|
|
|
Opts.SanitizeCoverage8bitCounters =
|
|
|
|
Args.hasArg(OPT_fsanitize_coverage_8bit_counters);
|
2016-02-18 05:34:43 +08:00
|
|
|
Opts.SanitizeCoverageTracePC = Args.hasArg(OPT_fsanitize_coverage_trace_pc);
|
2016-09-14 09:39:49 +08:00
|
|
|
Opts.SanitizeCoverageTracePCGuard =
|
|
|
|
Args.hasArg(OPT_fsanitize_coverage_trace_pc_guard);
|
2017-05-06 07:28:18 +08:00
|
|
|
Opts.SanitizeCoverageNoPrune = Args.hasArg(OPT_fsanitize_coverage_no_prune);
|
2017-06-09 06:58:19 +08:00
|
|
|
Opts.SanitizeCoverageInline8bitCounters =
|
|
|
|
Args.hasArg(OPT_fsanitize_coverage_inline_8bit_counters);
|
2017-07-28 08:10:10 +08:00
|
|
|
Opts.SanitizeCoveragePCTable = Args.hasArg(OPT_fsanitize_coverage_pc_table);
|
2017-08-19 02:43:30 +08:00
|
|
|
Opts.SanitizeCoverageStackDepth =
|
|
|
|
Args.hasArg(OPT_fsanitize_coverage_stack_depth);
|
2013-01-20 21:12:12 +08:00
|
|
|
Opts.SanitizeMemoryTrackOrigins =
|
2014-03-20 22:58:36 +08:00
|
|
|
getLastArgIntValue(Args, OPT_fsanitize_memory_track_origins_EQ, 0, Diags);
|
2015-07-11 04:07:16 +08:00
|
|
|
Opts.SanitizeMemoryUseAfterDtor =
|
2017-09-15 07:14:37 +08:00
|
|
|
Args.hasFlag(OPT_fsanitize_memory_use_after_dtor,
|
|
|
|
OPT_fno_sanitize_memory_use_after_dtor,
|
|
|
|
false);
|
2017-08-30 04:03:51 +08:00
|
|
|
Opts.SanitizeMinimalRuntime = Args.hasArg(OPT_fsanitize_minimal_runtime);
|
2015-12-16 07:00:20 +08:00
|
|
|
Opts.SanitizeCfiCrossDso = Args.hasArg(OPT_fsanitize_cfi_cross_dso);
|
2017-11-01 06:39:44 +08:00
|
|
|
Opts.SanitizeCfiICallGeneralizePointers =
|
|
|
|
Args.hasArg(OPT_fsanitize_cfi_icall_generalize_pointers);
|
cfi-icall: Allow the jump table to be optionally made non-canonical.
The default behavior of Clang's indirect function call checker will replace
the address of each CFI-checked function in the output file's symbol table
with the address of a jump table entry which will pass CFI checks. We refer
to this as making the jump table `canonical`. This property allows code that
was not compiled with ``-fsanitize=cfi-icall`` to take a CFI-valid address
of a function, but it comes with a couple of caveats that are especially
relevant for users of cross-DSO CFI:
- There is a performance and code size overhead associated with each
exported function, because each such function must have an associated
jump table entry, which must be emitted even in the common case where the
function is never address-taken anywhere in the program, and must be used
even for direct calls between DSOs, in addition to the PLT overhead.
- There is no good way to take a CFI-valid address of a function written in
assembly or a language not supported by Clang. The reason is that the code
generator would need to insert a jump table in order to form a CFI-valid
address for assembly functions, but there is no way in general for the
code generator to determine the language of the function. This may be
possible with LTO in the intra-DSO case, but in the cross-DSO case the only
information available is the function declaration. One possible solution
is to add a C wrapper for each assembly function, but these wrappers can
present a significant maintenance burden for heavy users of assembly in
addition to adding runtime overhead.
For these reasons, we provide the option of making the jump table non-canonical
with the flag ``-fno-sanitize-cfi-canonical-jump-tables``. When the jump
table is made non-canonical, symbol table entries point directly to the
function body. Any instances of a function's address being taken in C will
be replaced with a jump table address.
This scheme does have its own caveats, however. It does end up breaking
function address equality more aggressively than the default behavior,
especially in cross-DSO mode which normally preserves function address
equality entirely.
Furthermore, it is occasionally necessary for code not compiled with
``-fsanitize=cfi-icall`` to take a function address that is valid
for CFI. For example, this is necessary when a function's address
is taken by assembly code and then called by CFI-checking C code. The
``__attribute__((cfi_jump_table_canonical))`` attribute may be used to make
the jump table entry of a specific function canonical so that the external
code will end up taking a address for the function that will pass CFI checks.
Fixes PR41972.
Differential Revision: https://reviews.llvm.org/D65629
llvm-svn: 368495
2019-08-10 06:31:59 +08:00
|
|
|
Opts.SanitizeCfiCanonicalJumpTables =
|
|
|
|
Args.hasArg(OPT_fsanitize_cfi_canonical_jump_tables);
|
2016-01-16 08:31:22 +08:00
|
|
|
Opts.SanitizeStats = Args.hasArg(OPT_fsanitize_stats);
|
2018-02-12 19:49:02 +08:00
|
|
|
if (Arg *A = Args.getLastArg(
|
2018-11-03 01:29:04 +08:00
|
|
|
OPT_fsanitize_address_poison_custom_array_cookie,
|
|
|
|
OPT_fno_sanitize_address_poison_custom_array_cookie)) {
|
|
|
|
Opts.SanitizeAddressPoisonCustomArrayCookie =
|
2018-02-12 19:49:02 +08:00
|
|
|
A->getOption().getID() ==
|
2018-11-03 01:29:04 +08:00
|
|
|
OPT_fsanitize_address_poison_custom_array_cookie;
|
2018-02-12 19:49:02 +08:00
|
|
|
}
|
2016-10-11 05:31:50 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_fsanitize_address_use_after_scope,
|
|
|
|
OPT_fno_sanitize_address_use_after_scope)) {
|
|
|
|
Opts.SanitizeAddressUseAfterScope =
|
|
|
|
A->getOption().getID() == OPT_fsanitize_address_use_after_scope;
|
|
|
|
}
|
2017-05-10 05:57:43 +08:00
|
|
|
Opts.SanitizeAddressGlobalsDeadStripping =
|
|
|
|
Args.hasArg(OPT_fsanitize_address_globals_dead_stripping);
|
2018-12-05 09:44:31 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_fsanitize_address_use_odr_indicator,
|
|
|
|
OPT_fno_sanitize_address_use_odr_indicator)) {
|
|
|
|
Opts.SanitizeAddressUseOdrIndicator =
|
|
|
|
A->getOption().getID() == OPT_fsanitize_address_use_odr_indicator;
|
|
|
|
}
|
2012-08-22 00:16:06 +08:00
|
|
|
Opts.SSPBufferSize =
|
2013-06-15 01:17:23 +08:00
|
|
|
getLastArgIntValue(Args, OPT_stack_protector_buffer_size, 8, Diags);
|
2011-12-06 11:33:03 +08:00
|
|
|
Opts.StackRealignment = Args.hasArg(OPT_mstackrealign);
|
2011-12-06 07:05:23 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_mstack_alignment)) {
|
2012-11-01 12:30:05 +08:00
|
|
|
StringRef Val = A->getValue();
|
2012-10-24 04:05:01 +08:00
|
|
|
unsigned StackAlignment = Opts.StackAlignment;
|
|
|
|
Val.getAsInteger(10, StackAlignment);
|
|
|
|
Opts.StackAlignment = StackAlignment;
|
2011-12-06 07:05:23 +08:00
|
|
|
}
|
2010-06-22 08:03:40 +08:00
|
|
|
|
2015-01-21 03:45:50 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_mstack_probe_size)) {
|
|
|
|
StringRef Val = A->getValue();
|
|
|
|
unsigned StackProbeSize = Opts.StackProbeSize;
|
|
|
|
Val.getAsInteger(0, StackProbeSize);
|
|
|
|
Opts.StackProbeSize = StackProbeSize;
|
|
|
|
}
|
|
|
|
|
2018-02-23 21:47:36 +08:00
|
|
|
Opts.NoStackArgProbe = Args.hasArg(OPT_mno_stack_arg_probe);
|
|
|
|
|
2010-04-25 01:56:46 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_fobjc_dispatch_method_EQ)) {
|
2012-11-01 12:30:05 +08:00
|
|
|
StringRef Name = A->getValue();
|
2010-04-25 01:56:46 +08:00
|
|
|
unsigned Method = llvm::StringSwitch<unsigned>(Name)
|
|
|
|
.Case("legacy", CodeGenOptions::Legacy)
|
|
|
|
.Case("non-legacy", CodeGenOptions::NonLegacy)
|
|
|
|
.Case("mixed", CodeGenOptions::Mixed)
|
|
|
|
.Default(~0U);
|
2011-12-23 11:05:38 +08:00
|
|
|
if (Method == ~0U) {
|
2010-04-25 01:56:46 +08:00
|
|
|
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
|
2011-12-23 11:05:38 +08:00
|
|
|
Success = false;
|
|
|
|
} else {
|
2012-10-24 04:05:01 +08:00
|
|
|
Opts.setObjCDispatchMethod(
|
|
|
|
static_cast<CodeGenOptions::ObjCDispatchMethodKind>(Method));
|
2011-12-23 11:05:38 +08:00
|
|
|
}
|
2010-04-25 01:56:46 +08:00
|
|
|
}
|
2011-12-23 11:05:38 +08:00
|
|
|
|
2018-12-08 13:13:50 +08:00
|
|
|
|
|
|
|
if (Args.hasArg(OPT_fno_objc_convert_messages_to_runtime_calls))
|
|
|
|
Opts.ObjCConvertMessagesToRuntimeCalls = 0;
|
|
|
|
|
2018-03-02 06:26:19 +08:00
|
|
|
if (Args.getLastArg(OPT_femulated_tls) ||
|
|
|
|
Args.getLastArg(OPT_fno_emulated_tls)) {
|
|
|
|
Opts.ExplicitEmulatedTLS = true;
|
|
|
|
Opts.EmulatedTLS =
|
|
|
|
Args.hasFlag(OPT_femulated_tls, OPT_fno_emulated_tls, false);
|
|
|
|
}
|
2015-07-29 00:27:56 +08:00
|
|
|
|
2012-06-28 16:01:44 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_ftlsmodel_EQ)) {
|
2012-11-01 12:30:05 +08:00
|
|
|
StringRef Name = A->getValue();
|
2012-06-28 16:01:44 +08:00
|
|
|
unsigned Model = llvm::StringSwitch<unsigned>(Name)
|
|
|
|
.Case("global-dynamic", CodeGenOptions::GeneralDynamicTLSModel)
|
|
|
|
.Case("local-dynamic", CodeGenOptions::LocalDynamicTLSModel)
|
|
|
|
.Case("initial-exec", CodeGenOptions::InitialExecTLSModel)
|
|
|
|
.Case("local-exec", CodeGenOptions::LocalExecTLSModel)
|
|
|
|
.Default(~0U);
|
|
|
|
if (Model == ~0U) {
|
|
|
|
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
|
|
|
|
Success = false;
|
|
|
|
} else {
|
2012-10-24 04:05:01 +08:00
|
|
|
Opts.setDefaultTLSModel(static_cast<CodeGenOptions::TLSModel>(Model));
|
2012-06-28 16:01:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-30 16:09:45 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_EQ)) {
|
|
|
|
StringRef Val = A->getValue();
|
|
|
|
if (Val == "ieee")
|
|
|
|
Opts.FPDenormalMode = "ieee";
|
|
|
|
else if (Val == "preserve-sign")
|
|
|
|
Opts.FPDenormalMode = "preserve-sign";
|
|
|
|
else if (Val == "positive-zero")
|
|
|
|
Opts.FPDenormalMode = "positive-zero";
|
|
|
|
else
|
|
|
|
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
|
|
|
|
}
|
|
|
|
|
2013-06-18 10:46:29 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_fpcc_struct_return, OPT_freg_struct_return)) {
|
|
|
|
if (A->getOption().matches(OPT_fpcc_struct_return)) {
|
|
|
|
Opts.setStructReturnConvention(CodeGenOptions::SRCK_OnStack);
|
|
|
|
} else {
|
|
|
|
assert(A->getOption().matches(OPT_freg_struct_return));
|
|
|
|
Opts.setStructReturnConvention(CodeGenOptions::SRCK_InRegs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-08 08:17:41 +08:00
|
|
|
Opts.DependentLibraries = Args.getAllArgValues(OPT_dependent_lib);
|
2016-01-16 08:31:22 +08:00
|
|
|
Opts.LinkerOptions = Args.getAllArgValues(OPT_linker_option);
|
2014-06-25 01:02:17 +08:00
|
|
|
bool NeedLocTracking = false;
|
2013-08-08 08:17:41 +08:00
|
|
|
|
2016-10-11 08:26:09 +08:00
|
|
|
Opts.OptRecordFile = Args.getLastArgValue(OPT_opt_record_file);
|
|
|
|
if (!Opts.OptRecordFile.empty())
|
|
|
|
NeedLocTracking = true;
|
|
|
|
|
2019-03-13 05:22:27 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_opt_record_passes)) {
|
|
|
|
Opts.OptRecordPasses = A->getValue();
|
|
|
|
NeedLocTracking = true;
|
|
|
|
}
|
|
|
|
|
2019-06-18 00:06:00 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_opt_record_format)) {
|
|
|
|
Opts.OptRecordFormat = A->getValue();
|
|
|
|
NeedLocTracking = true;
|
|
|
|
}
|
|
|
|
|
2014-06-25 01:02:17 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_Rpass_EQ)) {
|
2014-05-30 03:55:06 +08:00
|
|
|
Opts.OptimizationRemarkPattern =
|
|
|
|
GenerateOptimizationRemarkRegex(Diags, Args, A);
|
2014-06-25 01:02:17 +08:00
|
|
|
NeedLocTracking = true;
|
|
|
|
}
|
2014-05-30 03:55:06 +08:00
|
|
|
|
2014-06-25 01:02:17 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_Rpass_missed_EQ)) {
|
2014-05-30 03:55:06 +08:00
|
|
|
Opts.OptimizationRemarkMissedPattern =
|
|
|
|
GenerateOptimizationRemarkRegex(Diags, Args, A);
|
2014-06-25 01:02:17 +08:00
|
|
|
NeedLocTracking = true;
|
|
|
|
}
|
2014-05-30 03:55:06 +08:00
|
|
|
|
2014-06-25 01:02:17 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_Rpass_analysis_EQ)) {
|
2014-05-30 03:55:06 +08:00
|
|
|
Opts.OptimizationRemarkAnalysisPattern =
|
|
|
|
GenerateOptimizationRemarkRegex(Diags, Args, A);
|
2014-06-25 01:02:17 +08:00
|
|
|
NeedLocTracking = true;
|
|
|
|
}
|
|
|
|
|
2016-09-13 12:32:40 +08:00
|
|
|
Opts.DiagnosticsWithHotness =
|
|
|
|
Args.hasArg(options::OPT_fdiagnostics_show_hotness);
|
2017-06-23 10:38:45 +08:00
|
|
|
bool UsingSampleProfile = !Opts.SampleProfileFile.empty();
|
2017-07-01 13:45:26 +08:00
|
|
|
bool UsingProfile = UsingSampleProfile ||
|
|
|
|
(Opts.getProfileUse() != CodeGenOptions::ProfileNone);
|
|
|
|
|
2018-05-05 22:37:29 +08:00
|
|
|
if (Opts.DiagnosticsWithHotness && !UsingProfile &&
|
|
|
|
// An IR file will contain PGO as metadata
|
2019-08-05 21:59:26 +08:00
|
|
|
IK.getLanguage() != Language::LLVM_IR)
|
2017-07-01 13:45:26 +08:00
|
|
|
Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo)
|
|
|
|
<< "-fdiagnostics-show-hotness";
|
|
|
|
|
|
|
|
Opts.DiagnosticsHotnessThreshold = getLastArgUInt64Value(
|
|
|
|
Args, options::OPT_fdiagnostics_hotness_threshold_EQ, 0);
|
|
|
|
if (Opts.DiagnosticsHotnessThreshold > 0 && !UsingProfile)
|
|
|
|
Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo)
|
|
|
|
<< "-fdiagnostics-hotness-threshold=";
|
2016-09-13 12:32:40 +08:00
|
|
|
|
2014-10-22 21:00:05 +08:00
|
|
|
// If the user requested to use a sample profile for PGO, then the
|
|
|
|
// backend will need to track source location information so the profile
|
|
|
|
// can be incorporated into the IR.
|
2017-06-23 10:38:45 +08:00
|
|
|
if (UsingSampleProfile)
|
2014-10-22 21:00:05 +08:00
|
|
|
NeedLocTracking = true;
|
|
|
|
|
|
|
|
// If the user requested a flag that requires source locations available in
|
|
|
|
// the backend, make sure that the backend tracks source location information.
|
2016-02-02 19:06:51 +08:00
|
|
|
if (NeedLocTracking && Opts.getDebugInfo() == codegenoptions::NoDebugInfo)
|
|
|
|
Opts.setDebugInfo(codegenoptions::LocTrackingOnly);
|
2014-05-30 03:55:06 +08:00
|
|
|
|
2015-01-09 13:10:20 +08:00
|
|
|
Opts.RewriteMapFiles = Args.getAllArgValues(OPT_frewrite_map_file);
|
|
|
|
|
Reimplement -fsanitize-recover family of flags.
Introduce the following -fsanitize-recover flags:
- -fsanitize-recover=<list>: Enable recovery for selected checks or
group of checks. It is forbidden to explicitly list unrecoverable
sanitizers here (that is, "address", "unreachable", "return").
- -fno-sanitize-recover=<list>: Disable recovery for selected checks or
group of checks.
- -f(no-)?sanitize-recover is now a synonym for
-f(no-)?sanitize-recover=undefined,integer and will soon be deprecated.
These flags are parsed left to right, and mask of "recoverable"
sanitizer is updated accordingly, much like what we do for -fsanitize= flags.
-fsanitize= and -fsanitize-recover= flag families are independent.
CodeGen change: If there is a single UBSan handler function, responsible
for implementing multiple checks, which have different recoverable setting,
then we emit two handler calls instead of one:
the first one for the set of "unrecoverable" checks, another one - for
set of "recoverable" checks. If all checks implemented by a handler have the
same recoverability setting, then the generated code will be the same.
llvm-svn: 225719
2015-01-13 06:39:12 +08:00
|
|
|
// Parse -fsanitize-recover= arguments.
|
|
|
|
// FIXME: Report unrecoverable sanitizers incorrectly specified here.
|
|
|
|
parseSanitizerKinds("-fsanitize-recover=",
|
|
|
|
Args.getAllArgValues(OPT_fsanitize_recover_EQ), Diags,
|
|
|
|
Opts.SanitizeRecover);
|
2015-06-19 07:59:22 +08:00
|
|
|
parseSanitizerKinds("-fsanitize-trap=",
|
|
|
|
Args.getAllArgValues(OPT_fsanitize_trap_EQ), Diags,
|
|
|
|
Opts.SanitizeTrap);
|
Reimplement -fsanitize-recover family of flags.
Introduce the following -fsanitize-recover flags:
- -fsanitize-recover=<list>: Enable recovery for selected checks or
group of checks. It is forbidden to explicitly list unrecoverable
sanitizers here (that is, "address", "unreachable", "return").
- -fno-sanitize-recover=<list>: Disable recovery for selected checks or
group of checks.
- -f(no-)?sanitize-recover is now a synonym for
-f(no-)?sanitize-recover=undefined,integer and will soon be deprecated.
These flags are parsed left to right, and mask of "recoverable"
sanitizer is updated accordingly, much like what we do for -fsanitize= flags.
-fsanitize= and -fsanitize-recover= flag families are independent.
CodeGen change: If there is a single UBSan handler function, responsible
for implementing multiple checks, which have different recoverable setting,
then we emit two handler calls instead of one:
the first one for the set of "unrecoverable" checks, another one - for
set of "recoverable" checks. If all checks implemented by a handler have the
same recoverability setting, then the generated code will be the same.
llvm-svn: 225719
2015-01-13 06:39:12 +08:00
|
|
|
|
2018-03-01 01:53:46 +08:00
|
|
|
Opts.CudaGpuBinaryFileName =
|
|
|
|
Args.getLastArgValue(OPT_fcuda_include_gpubinary);
|
2015-05-08 03:34:16 +08:00
|
|
|
|
2016-05-05 07:37:40 +08:00
|
|
|
Opts.Backchain = Args.hasArg(OPT_mbackchain);
|
|
|
|
|
2016-05-13 00:51:36 +08:00
|
|
|
Opts.EmitCheckPathComponentsToStrip = getLastArgIntValue(
|
|
|
|
Args, OPT_fsanitize_undefined_strip_path_components_EQ, 0, Diags);
|
|
|
|
|
2018-04-23 18:08:46 +08:00
|
|
|
Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true);
|
|
|
|
|
2018-07-18 08:27:07 +08:00
|
|
|
Opts.Addrsig = Args.hasArg(OPT_faddrsig);
|
|
|
|
|
2018-10-25 23:23:49 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_msign_return_address_EQ)) {
|
2018-08-17 20:55:05 +08:00
|
|
|
StringRef SignScope = A->getValue();
|
2018-10-25 23:23:49 +08:00
|
|
|
|
2018-08-17 20:55:05 +08:00
|
|
|
if (SignScope.equals_lower("none"))
|
|
|
|
Opts.setSignReturnAddress(CodeGenOptions::SignReturnAddressScope::None);
|
|
|
|
else if (SignScope.equals_lower("all"))
|
|
|
|
Opts.setSignReturnAddress(CodeGenOptions::SignReturnAddressScope::All);
|
|
|
|
else if (SignScope.equals_lower("non-leaf"))
|
|
|
|
Opts.setSignReturnAddress(
|
|
|
|
CodeGenOptions::SignReturnAddressScope::NonLeaf);
|
|
|
|
else
|
|
|
|
Diags.Report(diag::err_drv_invalid_value)
|
2018-10-25 23:23:49 +08:00
|
|
|
<< A->getAsString(Args) << SignScope;
|
|
|
|
|
|
|
|
if (Arg *A = Args.getLastArg(OPT_msign_return_address_key_EQ)) {
|
|
|
|
StringRef SignKey = A->getValue();
|
|
|
|
if (!SignScope.empty() && !SignKey.empty()) {
|
|
|
|
if (SignKey.equals_lower("a_key"))
|
|
|
|
Opts.setSignReturnAddressKey(
|
|
|
|
CodeGenOptions::SignReturnAddressKeyValue::AKey);
|
|
|
|
else if (SignKey.equals_lower("b_key"))
|
|
|
|
Opts.setSignReturnAddressKey(
|
|
|
|
CodeGenOptions::SignReturnAddressKeyValue::BKey);
|
|
|
|
else
|
|
|
|
Diags.Report(diag::err_drv_invalid_value)
|
|
|
|
<< A->getAsString(Args) << SignKey;
|
|
|
|
}
|
|
|
|
}
|
2018-08-17 20:55:05 +08:00
|
|
|
}
|
|
|
|
|
2018-10-25 23:23:49 +08:00
|
|
|
Opts.BranchTargetEnforcement = Args.hasArg(OPT_mbranch_target_enforce);
|
|
|
|
|
2018-08-23 03:05:19 +08:00
|
|
|
Opts.KeepStaticConsts = Args.hasArg(OPT_fkeep_static_consts);
|
|
|
|
|
2018-09-04 20:38:00 +08:00
|
|
|
Opts.SpeculativeLoadHardening = Args.hasArg(OPT_mspeculative_load_hardening);
|
|
|
|
|
2019-01-05 03:27:04 +08:00
|
|
|
Opts.DefaultFunctionAttrs = Args.getAllArgValues(OPT_default_function_attr);
|
|
|
|
|
2019-02-03 07:19:32 +08:00
|
|
|
Opts.PassPlugins = Args.getAllArgValues(OPT_fpass_plugin_EQ);
|
|
|
|
|
2019-06-08 03:10:08 +08:00
|
|
|
Opts.SymbolPartition = Args.getLastArgValue(OPT_fsymbol_partition_EQ);
|
|
|
|
|
2011-12-23 11:05:38 +08:00
|
|
|
return Success;
|
2009-12-01 11:16:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
|
|
|
|
ArgList &Args) {
|
2010-05-21 00:54:55 +08:00
|
|
|
Opts.OutputFile = Args.getLastArgValue(OPT_dependency_file);
|
|
|
|
Opts.Targets = Args.getAllArgValues(OPT_MT);
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.IncludeSystemHeaders = Args.hasArg(OPT_sys_header_deps);
|
2014-03-14 11:07:38 +08:00
|
|
|
Opts.IncludeModuleFiles = Args.hasArg(OPT_module_file_deps);
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.UsePhonyTargets = Args.hasArg(OPT_MP);
|
2011-02-02 23:41:17 +08:00
|
|
|
Opts.ShowHeaderIncludes = Args.hasArg(OPT_H);
|
2011-02-03 05:11:31 +08:00
|
|
|
Opts.HeaderIncludeOutputFile = Args.getLastArgValue(OPT_header_include_file);
|
2011-07-13 03:35:15 +08:00
|
|
|
Opts.AddMissingHeaderDeps = Args.hasArg(OPT_MG);
|
2018-05-04 23:58:31 +08:00
|
|
|
if (Args.hasArg(OPT_show_includes)) {
|
|
|
|
// Writing both /showIncludes and preprocessor output to stdout
|
|
|
|
// would produce interleaved output, so use stderr for /showIncludes.
|
|
|
|
// This behaves the same as cl.exe, when /E, /EP or /P are passed.
|
|
|
|
if (Args.hasArg(options::OPT_E) || Args.hasArg(options::OPT_P))
|
|
|
|
Opts.ShowIncludesDest = ShowIncludesDestination::Stderr;
|
|
|
|
else
|
|
|
|
Opts.ShowIncludesDest = ShowIncludesDestination::Stdout;
|
|
|
|
} else {
|
|
|
|
Opts.ShowIncludesDest = ShowIncludesDestination::None;
|
|
|
|
}
|
2012-02-03 07:45:13 +08:00
|
|
|
Opts.DOTOutputFile = Args.getLastArgValue(OPT_dependency_dot);
|
2014-06-20 03:36:03 +08:00
|
|
|
Opts.ModuleDependencyOutputDir =
|
|
|
|
Args.getLastArgValue(OPT_module_dependency_dir);
|
2015-04-28 02:14:32 +08:00
|
|
|
if (Args.hasArg(OPT_MV))
|
|
|
|
Opts.OutputFormat = DependencyOutputFormat::NMake;
|
2015-08-13 12:04:37 +08:00
|
|
|
// Add sanitizer blacklists as extra dependencies.
|
|
|
|
// They won't be discovered by the regular preprocessor, so
|
|
|
|
// we let make / ninja to know about this implicit dependency.
|
2015-09-03 04:02:38 +08:00
|
|
|
Opts.ExtraDeps = Args.getAllArgValues(OPT_fdepfile_entry);
|
2017-08-31 14:26:43 +08:00
|
|
|
// Only the -fmodule-file=<file> form.
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *A : Args.filtered(OPT_fmodule_file)) {
|
2017-08-31 14:26:43 +08:00
|
|
|
StringRef Val = A->getValue();
|
|
|
|
if (Val.find('=') == StringRef::npos)
|
|
|
|
Opts.ExtraDeps.push_back(Val);
|
|
|
|
}
|
2009-12-01 11:16:53 +08:00
|
|
|
}
|
|
|
|
|
2016-05-28 04:43:00 +08:00
|
|
|
static bool parseShowColorsArgs(const ArgList &Args, bool DefaultColor) {
|
|
|
|
// Color diagnostics default to auto ("on" if terminal supports) in the driver
|
|
|
|
// but default to off in cc1, needing an explicit OPT_fdiagnostics_color.
|
|
|
|
// Support both clang's -f[no-]color-diagnostics and gcc's
|
|
|
|
// -f[no-]diagnostics-colors[=never|always|auto].
|
|
|
|
enum {
|
|
|
|
Colors_On,
|
|
|
|
Colors_Off,
|
|
|
|
Colors_Auto
|
|
|
|
} ShowColors = DefaultColor ? Colors_Auto : Colors_Off;
|
2018-03-27 05:45:04 +08:00
|
|
|
for (auto *A : Args) {
|
2016-05-28 04:43:00 +08:00
|
|
|
const Option &O = A->getOption();
|
|
|
|
if (O.matches(options::OPT_fcolor_diagnostics) ||
|
|
|
|
O.matches(options::OPT_fdiagnostics_color)) {
|
|
|
|
ShowColors = Colors_On;
|
|
|
|
} else if (O.matches(options::OPT_fno_color_diagnostics) ||
|
|
|
|
O.matches(options::OPT_fno_diagnostics_color)) {
|
|
|
|
ShowColors = Colors_Off;
|
2016-12-10 22:55:14 +08:00
|
|
|
} else if (O.matches(options::OPT_fdiagnostics_color_EQ)) {
|
2016-05-28 04:43:00 +08:00
|
|
|
StringRef Value(A->getValue());
|
|
|
|
if (Value == "always")
|
|
|
|
ShowColors = Colors_On;
|
|
|
|
else if (Value == "never")
|
|
|
|
ShowColors = Colors_Off;
|
|
|
|
else if (Value == "auto")
|
|
|
|
ShowColors = Colors_Auto;
|
|
|
|
}
|
|
|
|
}
|
2016-12-10 22:55:14 +08:00
|
|
|
return ShowColors == Colors_On ||
|
|
|
|
(ShowColors == Colors_Auto &&
|
|
|
|
llvm::sys::Process::StandardErrHasColors());
|
2016-05-28 04:43:00 +08:00
|
|
|
}
|
|
|
|
|
2017-12-16 10:23:22 +08:00
|
|
|
static bool checkVerifyPrefixes(const std::vector<std::string> &VerifyPrefixes,
|
|
|
|
DiagnosticsEngine *Diags) {
|
|
|
|
bool Success = true;
|
|
|
|
for (const auto &Prefix : VerifyPrefixes) {
|
|
|
|
// Every prefix must start with a letter and contain only alphanumeric
|
|
|
|
// characters, hyphens, and underscores.
|
2019-03-31 16:48:19 +08:00
|
|
|
auto BadChar = llvm::find_if(Prefix, [](char C) {
|
|
|
|
return !isAlphanumeric(C) && C != '-' && C != '_';
|
|
|
|
});
|
2017-12-16 10:23:22 +08:00
|
|
|
if (BadChar != Prefix.end() || !isLetter(Prefix[0])) {
|
|
|
|
Success = false;
|
|
|
|
if (Diags) {
|
|
|
|
Diags->Report(diag::err_drv_invalid_value) << "-verify=" << Prefix;
|
|
|
|
Diags->Report(diag::note_drv_verify_prefix_spelling);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
2012-03-14 04:09:56 +08:00
|
|
|
bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
|
2016-05-28 04:43:00 +08:00
|
|
|
DiagnosticsEngine *Diags,
|
2016-10-12 02:21:26 +08:00
|
|
|
bool DefaultDiagColor, bool DefaultShowOpt) {
|
2011-12-23 11:05:38 +08:00
|
|
|
bool Success = true;
|
|
|
|
|
2011-04-08 02:11:14 +08:00
|
|
|
Opts.DiagnosticLogFile = Args.getLastArgValue(OPT_diagnostic_log_file);
|
2014-10-24 06:20:11 +08:00
|
|
|
if (Arg *A =
|
|
|
|
Args.getLastArg(OPT_diagnostic_serialized_file, OPT__serialize_diags))
|
|
|
|
Opts.DiagnosticSerializationFile = A->getValue();
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.IgnoreWarnings = Args.hasArg(OPT_w);
|
|
|
|
Opts.NoRewriteMacros = Args.hasArg(OPT_Wno_rewrite_macros);
|
|
|
|
Opts.Pedantic = Args.hasArg(OPT_pedantic);
|
|
|
|
Opts.PedanticErrors = Args.hasArg(OPT_pedantic_errors);
|
|
|
|
Opts.ShowCarets = !Args.hasArg(OPT_fno_caret_diagnostics);
|
2016-05-28 04:43:00 +08:00
|
|
|
Opts.ShowColors = parseShowColorsArgs(Args, DefaultDiagColor);
|
2011-05-22 01:07:29 +08:00
|
|
|
Opts.ShowColumn = Args.hasFlag(OPT_fshow_column,
|
|
|
|
OPT_fno_show_column,
|
|
|
|
/*Default=*/true);
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.ShowFixits = !Args.hasArg(OPT_fno_diagnostics_fixit_info);
|
|
|
|
Opts.ShowLocation = !Args.hasArg(OPT_fno_show_source_location);
|
2016-08-26 23:45:36 +08:00
|
|
|
Opts.AbsolutePath = Args.hasArg(OPT_fdiagnostics_absolute_paths);
|
2016-10-12 02:21:26 +08:00
|
|
|
Opts.ShowOptionNames =
|
|
|
|
Args.hasFlag(OPT_fdiagnostics_show_option,
|
|
|
|
OPT_fno_diagnostics_show_option, DefaultShowOpt);
|
2010-06-11 13:57:47 +08:00
|
|
|
|
2013-09-11 08:38:02 +08:00
|
|
|
llvm::sys::Process::UseANSIEscapeCodes(Args.hasArg(OPT_fansi_escape_codes));
|
|
|
|
|
2011-03-28 04:00:08 +08:00
|
|
|
// Default behavior is to not to show note include stacks.
|
|
|
|
Opts.ShowNoteIncludeStack = false;
|
2011-03-27 09:50:55 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_fdiagnostics_show_note_include_stack,
|
|
|
|
OPT_fno_diagnostics_show_note_include_stack))
|
2011-03-28 04:00:08 +08:00
|
|
|
if (A->getOption().matches(OPT_fdiagnostics_show_note_include_stack))
|
|
|
|
Opts.ShowNoteIncludeStack = true;
|
2011-03-27 09:50:55 +08:00
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef ShowOverloads =
|
2010-06-11 13:57:47 +08:00
|
|
|
Args.getLastArgValue(OPT_fshow_overloads_EQ, "all");
|
|
|
|
if (ShowOverloads == "best")
|
2012-10-24 07:11:23 +08:00
|
|
|
Opts.setShowOverloads(Ovl_Best);
|
2010-06-11 13:57:47 +08:00
|
|
|
else if (ShowOverloads == "all")
|
2012-10-24 07:11:23 +08:00
|
|
|
Opts.setShowOverloads(Ovl_All);
|
2011-12-23 11:05:38 +08:00
|
|
|
else {
|
2012-03-14 04:09:56 +08:00
|
|
|
Success = false;
|
|
|
|
if (Diags)
|
|
|
|
Diags->Report(diag::err_drv_invalid_value)
|
2010-06-11 13:57:47 +08:00
|
|
|
<< Args.getLastArg(OPT_fshow_overloads_EQ)->getAsString(Args)
|
|
|
|
<< ShowOverloads;
|
2011-12-23 11:05:38 +08:00
|
|
|
}
|
2010-06-11 13:57:47 +08:00
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef ShowCategory =
|
2010-05-21 00:54:55 +08:00
|
|
|
Args.getLastArgValue(OPT_fdiagnostics_show_category, "none");
|
2010-05-05 05:55:25 +08:00
|
|
|
if (ShowCategory == "none")
|
|
|
|
Opts.ShowCategories = 0;
|
|
|
|
else if (ShowCategory == "id")
|
|
|
|
Opts.ShowCategories = 1;
|
|
|
|
else if (ShowCategory == "name")
|
|
|
|
Opts.ShowCategories = 2;
|
2011-12-23 11:05:38 +08:00
|
|
|
else {
|
2012-03-14 04:09:56 +08:00
|
|
|
Success = false;
|
|
|
|
if (Diags)
|
|
|
|
Diags->Report(diag::err_drv_invalid_value)
|
2010-05-05 05:55:25 +08:00
|
|
|
<< Args.getLastArg(OPT_fdiagnostics_show_category)->getAsString(Args)
|
|
|
|
<< ShowCategory;
|
2011-12-23 11:05:38 +08:00
|
|
|
}
|
2010-10-21 11:16:25 +08:00
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef Format =
|
2011-05-22 01:07:29 +08:00
|
|
|
Args.getLastArgValue(OPT_fdiagnostics_format, "clang");
|
|
|
|
if (Format == "clang")
|
2012-10-24 07:11:23 +08:00
|
|
|
Opts.setFormat(DiagnosticOptions::Clang);
|
2011-12-23 11:05:38 +08:00
|
|
|
else if (Format == "msvc")
|
2015-02-03 03:30:52 +08:00
|
|
|
Opts.setFormat(DiagnosticOptions::MSVC);
|
2013-09-24 08:08:55 +08:00
|
|
|
else if (Format == "msvc-fallback") {
|
2015-02-03 03:30:52 +08:00
|
|
|
Opts.setFormat(DiagnosticOptions::MSVC);
|
2013-09-24 08:08:55 +08:00
|
|
|
Opts.CLFallbackMode = true;
|
|
|
|
} else if (Format == "vi")
|
2012-10-24 07:11:23 +08:00
|
|
|
Opts.setFormat(DiagnosticOptions::Vi);
|
2011-12-23 11:05:38 +08:00
|
|
|
else {
|
2012-03-14 04:09:56 +08:00
|
|
|
Success = false;
|
|
|
|
if (Diags)
|
|
|
|
Diags->Report(diag::err_drv_invalid_value)
|
2011-05-22 01:07:29 +08:00
|
|
|
<< Args.getLastArg(OPT_fdiagnostics_format)->getAsString(Args)
|
|
|
|
<< Format;
|
2011-12-23 11:05:38 +08:00
|
|
|
}
|
2015-06-13 15:11:40 +08:00
|
|
|
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info);
|
2010-08-20 04:24:43 +08:00
|
|
|
Opts.ShowParseableFixits = Args.hasArg(OPT_fdiagnostics_parseable_fixits);
|
2012-11-15 07:55:25 +08:00
|
|
|
Opts.ShowPresumedLoc = !Args.hasArg(OPT_fno_diagnostics_use_presumed_location);
|
2017-12-16 10:23:22 +08:00
|
|
|
Opts.VerifyDiagnostics = Args.hasArg(OPT_verify) || Args.hasArg(OPT_verify_EQ);
|
|
|
|
Opts.VerifyPrefixes = Args.getAllArgValues(OPT_verify_EQ);
|
|
|
|
if (Args.hasArg(OPT_verify))
|
|
|
|
Opts.VerifyPrefixes.push_back("expected");
|
|
|
|
// Keep VerifyPrefixes in its original order for the sake of diagnostics, and
|
|
|
|
// then sort it to prepare for fast lookup using std::binary_search.
|
|
|
|
if (!checkVerifyPrefixes(Opts.VerifyPrefixes, Diags)) {
|
|
|
|
Opts.VerifyDiagnostics = false;
|
|
|
|
Success = false;
|
|
|
|
}
|
|
|
|
else
|
2018-10-01 05:41:11 +08:00
|
|
|
llvm::sort(Opts.VerifyPrefixes);
|
2015-06-13 15:11:40 +08:00
|
|
|
DiagnosticLevelMask DiagMask = DiagnosticLevelMask::None;
|
|
|
|
Success &= parseDiagnosticLevelMask("-verify-ignore-unexpected=",
|
|
|
|
Args.getAllArgValues(OPT_verify_ignore_unexpected_EQ),
|
|
|
|
Diags, DiagMask);
|
|
|
|
if (Args.hasArg(OPT_verify_ignore_unexpected))
|
|
|
|
DiagMask = DiagnosticLevelMask::All;
|
|
|
|
Opts.setVerifyIgnoreUnexpected(DiagMask);
|
2012-06-27 02:18:47 +08:00
|
|
|
Opts.ElideType = !Args.hasArg(OPT_fno_elide_type);
|
|
|
|
Opts.ShowTemplateTree = Args.hasArg(OPT_fdiagnostics_show_template_tree);
|
2013-06-15 01:17:23 +08:00
|
|
|
Opts.ErrorLimit = getLastArgIntValue(Args, OPT_ferror_limit, 0, Diags);
|
|
|
|
Opts.MacroBacktraceLimit =
|
|
|
|
getLastArgIntValue(Args, OPT_fmacro_backtrace_limit,
|
2010-05-05 01:13:42 +08:00
|
|
|
DiagnosticOptions::DefaultMacroBacktraceLimit, Diags);
|
2013-06-15 01:17:23 +08:00
|
|
|
Opts.TemplateBacktraceLimit = getLastArgIntValue(
|
|
|
|
Args, OPT_ftemplate_backtrace_limit,
|
|
|
|
DiagnosticOptions::DefaultTemplateBacktraceLimit, Diags);
|
|
|
|
Opts.ConstexprBacktraceLimit = getLastArgIntValue(
|
|
|
|
Args, OPT_fconstexpr_backtrace_limit,
|
|
|
|
DiagnosticOptions::DefaultConstexprBacktraceLimit, Diags);
|
2014-12-17 05:39:02 +08:00
|
|
|
Opts.SpellCheckingLimit = getLastArgIntValue(
|
|
|
|
Args, OPT_fspell_checking_limit,
|
|
|
|
DiagnosticOptions::DefaultSpellCheckingLimit, Diags);
|
2017-05-23 07:51:40 +08:00
|
|
|
Opts.SnippetLineLimit = getLastArgIntValue(
|
|
|
|
Args, OPT_fcaret_diagnostics_max_lines,
|
|
|
|
DiagnosticOptions::DefaultSnippetLineLimit, Diags);
|
2013-06-15 01:17:23 +08:00
|
|
|
Opts.TabStop = getLastArgIntValue(Args, OPT_ftabstop,
|
2010-01-13 11:06:50 +08:00
|
|
|
DiagnosticOptions::DefaultTabStop, Diags);
|
|
|
|
if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) {
|
|
|
|
Opts.TabStop = DiagnosticOptions::DefaultTabStop;
|
2012-03-14 04:09:56 +08:00
|
|
|
if (Diags)
|
|
|
|
Diags->Report(diag::warn_ignoring_ftabstop_value)
|
|
|
|
<< Opts.TabStop << DiagnosticOptions::DefaultTabStop;
|
2010-01-13 11:06:50 +08:00
|
|
|
}
|
2013-06-15 01:17:23 +08:00
|
|
|
Opts.MessageLength = getLastArgIntValue(Args, OPT_fmessage_length, 0, Diags);
|
Use -Rblah, not -Wblah, to control remark diagnostics. This was always the
intent when we added remark support, but was never implemented in the general
case, because the first -R flags didn't need it. (-Rpass= had special handling
to accomodate its argument.)
-Rno-foo, -Reverything, and -Rno-everything can be used to turn off a remark,
or to turn on or off all remarks. Per discussion on cfe-commits, -Weverything
does not affect remarks, and -Reverything does not affect warnings or errors.
The only "real" -R flag we have right now is -Rmodule-build; that flag is
effectively renamed from -Wmodule-build to -Rmodule-build by this change.
-Wpass and -Wno-pass (and their friends) are also renamed to -Rpass and
-Rno-pass by this change; it's not completely clear whether we intended to have
a -Rpass (with no =pattern), but that is unchanged by this commit, other than
the flag name. The default pattern is effectively one which matches no passes.
In future, we may want to make the default pattern be .*, so that -Reverything
works for -Rpass properly.
llvm-svn: 215046
2014-08-07 08:24:21 +08:00
|
|
|
addDiagnosticArgs(Args, OPT_W_Group, OPT_W_value_Group, Opts.Warnings);
|
|
|
|
addDiagnosticArgs(Args, OPT_R_Group, OPT_R_value_Group, Opts.Remarks);
|
2011-12-23 11:05:38 +08:00
|
|
|
|
|
|
|
return Success;
|
2009-12-01 11:16:53 +08:00
|
|
|
}
|
|
|
|
|
2010-11-04 06:45:23 +08:00
|
|
|
static void ParseFileSystemArgs(FileSystemOptions &Opts, ArgList &Args) {
|
|
|
|
Opts.WorkingDir = Args.getLastArgValue(OPT_working_directory);
|
|
|
|
}
|
|
|
|
|
2015-11-04 02:33:07 +08:00
|
|
|
/// Parse the argument to the -ftest-module-file-extension
|
|
|
|
/// command-line argument.
|
|
|
|
///
|
|
|
|
/// \returns true on error, false on success.
|
|
|
|
static bool parseTestModuleFileExtensionArg(StringRef Arg,
|
|
|
|
std::string &BlockName,
|
|
|
|
unsigned &MajorVersion,
|
|
|
|
unsigned &MinorVersion,
|
|
|
|
bool &Hashed,
|
|
|
|
std::string &UserInfo) {
|
|
|
|
SmallVector<StringRef, 5> Args;
|
|
|
|
Arg.split(Args, ':', 5);
|
|
|
|
if (Args.size() < 5)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
BlockName = Args[0];
|
|
|
|
if (Args[1].getAsInteger(10, MajorVersion)) return true;
|
|
|
|
if (Args[2].getAsInteger(10, MinorVersion)) return true;
|
|
|
|
if (Args[3].getAsInteger(2, Hashed)) return true;
|
|
|
|
if (Args.size() > 4)
|
|
|
|
UserInfo = Args[4];
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-06-08 07:22:09 +08:00
|
|
|
static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
|
2016-10-27 22:17:10 +08:00
|
|
|
DiagnosticsEngine &Diags,
|
|
|
|
bool &IsHeaderFile) {
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.ProgramAction = frontend::ParseSyntaxOnly;
|
|
|
|
if (const Arg *A = Args.getLastArg(OPT_Action_Group)) {
|
|
|
|
switch (A->getOption().getID()) {
|
|
|
|
default:
|
2011-09-23 13:06:16 +08:00
|
|
|
llvm_unreachable("Invalid option in group!");
|
2012-07-31 17:37:40 +08:00
|
|
|
case OPT_ast_list:
|
|
|
|
Opts.ProgramAction = frontend::ASTDeclList; break;
|
2019-05-14 05:39:55 +08:00
|
|
|
case OPT_ast_dump_all_EQ:
|
|
|
|
case OPT_ast_dump_EQ: {
|
|
|
|
unsigned Val = llvm::StringSwitch<unsigned>(A->getValue())
|
|
|
|
.CaseLower("default", ADOF_Default)
|
|
|
|
.CaseLower("json", ADOF_JSON)
|
|
|
|
.Default(std::numeric_limits<unsigned>::max());
|
|
|
|
|
|
|
|
if (Val != std::numeric_limits<unsigned>::max())
|
|
|
|
Opts.ASTDumpFormat = static_cast<ASTDumpOutputFormat>(Val);
|
|
|
|
else {
|
|
|
|
Diags.Report(diag::err_drv_invalid_value)
|
|
|
|
<< A->getAsString(Args) << A->getValue();
|
|
|
|
Opts.ASTDumpFormat = ADOF_Default;
|
|
|
|
}
|
|
|
|
LLVM_FALLTHROUGH;
|
|
|
|
}
|
2009-12-01 11:16:53 +08:00
|
|
|
case OPT_ast_dump:
|
2017-03-10 06:00:01 +08:00
|
|
|
case OPT_ast_dump_all:
|
2014-08-12 06:11:07 +08:00
|
|
|
case OPT_ast_dump_lookups:
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.ProgramAction = frontend::ASTDump; break;
|
|
|
|
case OPT_ast_print:
|
|
|
|
Opts.ProgramAction = frontend::ASTPrint; break;
|
|
|
|
case OPT_ast_view:
|
|
|
|
Opts.ProgramAction = frontend::ASTView; break;
|
2018-05-31 21:57:09 +08:00
|
|
|
case OPT_compiler_options_dump:
|
|
|
|
Opts.ProgramAction = frontend::DumpCompilerOptions; break;
|
2009-12-01 11:16:53 +08:00
|
|
|
case OPT_dump_raw_tokens:
|
|
|
|
Opts.ProgramAction = frontend::DumpRawTokens; break;
|
|
|
|
case OPT_dump_tokens:
|
|
|
|
Opts.ProgramAction = frontend::DumpTokens; break;
|
|
|
|
case OPT_S:
|
|
|
|
Opts.ProgramAction = frontend::EmitAssembly; break;
|
|
|
|
case OPT_emit_llvm_bc:
|
|
|
|
Opts.ProgramAction = frontend::EmitBC; break;
|
|
|
|
case OPT_emit_html:
|
|
|
|
Opts.ProgramAction = frontend::EmitHTML; break;
|
|
|
|
case OPT_emit_llvm:
|
|
|
|
Opts.ProgramAction = frontend::EmitLLVM; break;
|
|
|
|
case OPT_emit_llvm_only:
|
|
|
|
Opts.ProgramAction = frontend::EmitLLVMOnly; break;
|
2010-05-26 02:41:01 +08:00
|
|
|
case OPT_emit_codegen_only:
|
|
|
|
Opts.ProgramAction = frontend::EmitCodeGenOnly; break;
|
2010-02-03 09:18:43 +08:00
|
|
|
case OPT_emit_obj:
|
|
|
|
Opts.ProgramAction = frontend::EmitObj; break;
|
2010-04-24 09:30:46 +08:00
|
|
|
case OPT_fixit_EQ:
|
2012-11-01 12:30:05 +08:00
|
|
|
Opts.FixItSuffix = A->getValue();
|
Fix clang -Wimplicit-fallthrough warnings across llvm, NFC
This patch should not introduce any behavior changes. It consists of
mostly one of two changes:
1. Replacing fall through comments with the LLVM_FALLTHROUGH macro
2. Inserting 'break' before falling through into a case block consisting
of only 'break'.
We were already using this warning with GCC, but its warning behaves
slightly differently. In this patch, the following differences are
relevant:
1. GCC recognizes comments that say "fall through" as annotations, clang
doesn't
2. GCC doesn't warn on "case N: foo(); default: break;", clang does
3. GCC doesn't warn when the case contains a switch, but falls through
the outer case.
I will enable the warning separately in a follow-up patch so that it can
be cleanly reverted if necessary.
Reviewers: alexfh, rsmith, lattner, rtrieu, EricWF, bollu
Differential Revision: https://reviews.llvm.org/D53950
llvm-svn: 345882
2018-11-02 03:54:45 +08:00
|
|
|
LLVM_FALLTHROUGH;
|
2009-12-01 11:16:53 +08:00
|
|
|
case OPT_fixit:
|
|
|
|
Opts.ProgramAction = frontend::FixIt; break;
|
2011-08-26 06:30:56 +08:00
|
|
|
case OPT_emit_module:
|
|
|
|
Opts.ProgramAction = frontend::GenerateModule; break;
|
2016-08-26 08:14:38 +08:00
|
|
|
case OPT_emit_module_interface:
|
|
|
|
Opts.ProgramAction = frontend::GenerateModuleInterface; break;
|
2018-09-15 09:21:15 +08:00
|
|
|
case OPT_emit_header_module:
|
|
|
|
Opts.ProgramAction = frontend::GenerateHeaderModule; break;
|
2009-12-01 11:16:53 +08:00
|
|
|
case OPT_emit_pch:
|
|
|
|
Opts.ProgramAction = frontend::GeneratePCH; break;
|
2019-06-21 00:59:48 +08:00
|
|
|
case OPT_emit_iterface_stubs: {
|
2019-08-23 07:44:34 +08:00
|
|
|
StringRef ArgStr =
|
|
|
|
Args.hasArg(OPT_iterface_stub_version_EQ)
|
|
|
|
? Args.getLastArgValue(OPT_iterface_stub_version_EQ)
|
|
|
|
: "";
|
2019-06-21 00:59:48 +08:00
|
|
|
llvm::Optional<frontend::ActionKind> ProgramAction =
|
2019-08-23 07:44:34 +08:00
|
|
|
llvm::StringSwitch<llvm::Optional<frontend::ActionKind>>(ArgStr)
|
|
|
|
.Case("experimental-ifs-v1", frontend::GenerateInterfaceIfsExpV1)
|
2019-06-21 00:59:48 +08:00
|
|
|
.Default(llvm::None);
|
2019-08-23 07:44:34 +08:00
|
|
|
if (!ProgramAction) {
|
|
|
|
std::string ErrorMessage =
|
|
|
|
"Invalid interface stub format: " + ArgStr.str() +
|
|
|
|
((ArgStr == "experimental-yaml-elf-v1" ||
|
|
|
|
ArgStr == "experimental-tapi-elf-v1")
|
|
|
|
? " is deprecated."
|
|
|
|
: ".");
|
2019-06-21 00:59:48 +08:00
|
|
|
Diags.Report(diag::err_drv_invalid_value)
|
2019-08-23 07:44:34 +08:00
|
|
|
<< "Must specify a valid interface stub format type, ie: "
|
|
|
|
"-interface-stub-version=experimental-ifs-v1"
|
|
|
|
<< ErrorMessage;
|
|
|
|
} else {
|
|
|
|
Opts.ProgramAction = *ProgramAction;
|
|
|
|
}
|
2019-06-21 00:59:48 +08:00
|
|
|
break;
|
|
|
|
}
|
2010-03-20 03:44:04 +08:00
|
|
|
case OPT_init_only:
|
|
|
|
Opts.ProgramAction = frontend::InitOnly; break;
|
2009-12-01 11:16:53 +08:00
|
|
|
case OPT_fsyntax_only:
|
|
|
|
Opts.ProgramAction = frontend::ParseSyntaxOnly; break;
|
2013-03-28 00:47:18 +08:00
|
|
|
case OPT_module_file_info:
|
|
|
|
Opts.ProgramAction = frontend::ModuleFileInfo; break;
|
2014-02-06 06:21:15 +08:00
|
|
|
case OPT_verify_pch:
|
|
|
|
Opts.ProgramAction = frontend::VerifyPCH; break;
|
2010-07-21 04:18:03 +08:00
|
|
|
case OPT_print_preamble:
|
|
|
|
Opts.ProgramAction = frontend::PrintPreamble; break;
|
2009-12-01 11:16:53 +08:00
|
|
|
case OPT_E:
|
|
|
|
Opts.ProgramAction = frontend::PrintPreprocessedInput; break;
|
2018-02-10 22:04:45 +08:00
|
|
|
case OPT_templight_dump:
|
|
|
|
Opts.ProgramAction = frontend::TemplightDump; break;
|
2009-12-01 11:16:53 +08:00
|
|
|
case OPT_rewrite_macros:
|
|
|
|
Opts.ProgramAction = frontend::RewriteMacros; break;
|
|
|
|
case OPT_rewrite_objc:
|
|
|
|
Opts.ProgramAction = frontend::RewriteObjC; break;
|
|
|
|
case OPT_rewrite_test:
|
|
|
|
Opts.ProgramAction = frontend::RewriteTest; break;
|
|
|
|
case OPT_analyze:
|
|
|
|
Opts.ProgramAction = frontend::RunAnalysis; break;
|
2012-03-07 04:06:33 +08:00
|
|
|
case OPT_migrate:
|
|
|
|
Opts.ProgramAction = frontend::MigrateSource; break;
|
2009-12-01 11:16:53 +08:00
|
|
|
case OPT_Eonly:
|
|
|
|
Opts.ProgramAction = frontend::RunPreprocessorOnly; break;
|
2019-06-04 06:59:17 +08:00
|
|
|
case OPT_print_dependency_directives_minimized_source:
|
|
|
|
Opts.ProgramAction =
|
|
|
|
frontend::PrintDependencyDirectivesSourceMinimizerOutput;
|
|
|
|
break;
|
2009-12-01 11:16:53 +08:00
|
|
|
}
|
|
|
|
}
|
2010-06-17 00:59:23 +08:00
|
|
|
|
|
|
|
if (const Arg* A = Args.getLastArg(OPT_plugin)) {
|
2015-05-30 03:42:19 +08:00
|
|
|
Opts.Plugins.emplace_back(A->getValue(0));
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.ProgramAction = frontend::PluginAction;
|
2012-11-01 12:30:05 +08:00
|
|
|
Opts.ActionName = A->getValue();
|
2009-12-01 11:16:53 +08:00
|
|
|
}
|
2019-01-05 09:10:20 +08:00
|
|
|
Opts.AddPluginActions = Args.getAllArgValues(OPT_add_plugin);
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *AA : Args.filtered(OPT_plugin_arg))
|
2016-03-15 20:51:40 +08:00
|
|
|
Opts.PluginArgs[AA->getValue(0)].emplace_back(AA->getValue(1));
|
2011-01-26 04:34:14 +08:00
|
|
|
|
2015-11-04 02:33:07 +08:00
|
|
|
for (const std::string &Arg :
|
|
|
|
Args.getAllArgValues(OPT_ftest_module_file_extension_EQ)) {
|
|
|
|
std::string BlockName;
|
|
|
|
unsigned MajorVersion;
|
|
|
|
unsigned MinorVersion;
|
|
|
|
bool Hashed;
|
|
|
|
std::string UserInfo;
|
|
|
|
if (parseTestModuleFileExtensionArg(Arg, BlockName, MajorVersion,
|
|
|
|
MinorVersion, Hashed, UserInfo)) {
|
|
|
|
Diags.Report(diag::err_test_module_file_extension_format) << Arg;
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add the testing module file extension.
|
|
|
|
Opts.ModuleFileExtensions.push_back(
|
2017-01-06 02:23:18 +08:00
|
|
|
std::make_shared<TestModuleFileExtension>(
|
|
|
|
BlockName, MajorVersion, MinorVersion, Hashed, UserInfo));
|
2015-11-04 02:33:07 +08:00
|
|
|
}
|
|
|
|
|
2009-12-01 11:16:53 +08:00
|
|
|
if (const Arg *A = Args.getLastArg(OPT_code_completion_at)) {
|
|
|
|
Opts.CodeCompletionAt =
|
2012-11-01 12:30:05 +08:00
|
|
|
ParsedSourceLocation::FromString(A->getValue());
|
2009-12-01 11:16:53 +08:00
|
|
|
if (Opts.CodeCompletionAt.FileName.empty())
|
|
|
|
Diags.Report(diag::err_drv_invalid_value)
|
2012-11-01 12:30:05 +08:00
|
|
|
<< A->getAsString(Args) << A->getValue();
|
2009-12-01 11:16:53 +08:00
|
|
|
}
|
|
|
|
Opts.DisableFree = Args.hasArg(OPT_disable_free);
|
|
|
|
|
2010-05-21 00:54:55 +08:00
|
|
|
Opts.OutputFile = Args.getLastArgValue(OPT_o);
|
|
|
|
Opts.Plugins = Args.getAllArgValues(OPT_load);
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.RelocatablePCH = Args.hasArg(OPT_relocatable_pch);
|
2009-12-03 15:01:58 +08:00
|
|
|
Opts.ShowHelp = Args.hasArg(OPT_help);
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.ShowStats = Args.hasArg(OPT_print_stats);
|
|
|
|
Opts.ShowTimers = Args.hasArg(OPT_ftime_report);
|
2019-06-29 09:24:36 +08:00
|
|
|
Opts.PrintSupportedCPUs = Args.hasArg(OPT_print_supported_cpus);
|
2019-03-30 16:42:48 +08:00
|
|
|
Opts.TimeTrace = Args.hasArg(OPT_ftime_trace);
|
2019-07-24 22:55:40 +08:00
|
|
|
Opts.TimeTraceGranularity = getLastArgIntValue(
|
|
|
|
Args, OPT_ftime_trace_granularity_EQ, Opts.TimeTraceGranularity, Diags);
|
2009-12-03 15:01:58 +08:00
|
|
|
Opts.ShowVersion = Args.hasArg(OPT_version);
|
2010-05-21 00:54:55 +08:00
|
|
|
Opts.ASTMergeFiles = Args.getAllArgValues(OPT_ast_merge);
|
|
|
|
Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm);
|
2010-08-14 01:31:00 +08:00
|
|
|
Opts.FixWhatYouCan = Args.hasArg(OPT_fix_what_you_can);
|
2012-01-26 10:40:48 +08:00
|
|
|
Opts.FixOnlyWarnings = Args.hasArg(OPT_fix_only_warnings);
|
|
|
|
Opts.FixAndRecompile = Args.hasArg(OPT_fixit_recompile);
|
|
|
|
Opts.FixToTemporaries = Args.hasArg(OPT_fixit_to_temp);
|
2019-05-14 05:39:55 +08:00
|
|
|
Opts.ASTDumpDecls = Args.hasArg(OPT_ast_dump, OPT_ast_dump_EQ);
|
|
|
|
Opts.ASTDumpAll = Args.hasArg(OPT_ast_dump_all, OPT_ast_dump_all_EQ);
|
2012-07-27 00:01:23 +08:00
|
|
|
Opts.ASTDumpFilter = Args.getLastArgValue(OPT_ast_dump_filter);
|
2013-06-24 09:45:33 +08:00
|
|
|
Opts.ASTDumpLookups = Args.hasArg(OPT_ast_dump_lookups);
|
2013-01-29 02:38:02 +08:00
|
|
|
Opts.UseGlobalModuleIndex = !Args.hasArg(OPT_fno_modules_global_index);
|
2013-01-25 08:45:27 +08:00
|
|
|
Opts.GenerateGlobalModuleIndex = Opts.UseGlobalModuleIndex;
|
2014-12-06 09:13:41 +08:00
|
|
|
Opts.ModuleMapFiles = Args.getAllArgValues(OPT_fmodule_map_file);
|
2017-08-31 14:26:43 +08:00
|
|
|
// Only the -fmodule-file=<file> form.
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *A : Args.filtered(OPT_fmodule_file)) {
|
2017-08-31 14:26:43 +08:00
|
|
|
StringRef Val = A->getValue();
|
|
|
|
if (Val.find('=') == StringRef::npos)
|
|
|
|
Opts.ModuleFiles.push_back(Val);
|
|
|
|
}
|
2015-08-14 13:02:58 +08:00
|
|
|
Opts.ModulesEmbedFiles = Args.getAllArgValues(OPT_fmodules_embed_file_EQ);
|
2015-11-24 12:22:21 +08:00
|
|
|
Opts.ModulesEmbedAllFiles = Args.hasArg(OPT_fmodules_embed_all_files);
|
2016-07-13 22:21:11 +08:00
|
|
|
Opts.IncludeTimestamps = !Args.hasArg(OPT_fno_pch_timestamp);
|
2014-10-22 10:05:46 +08:00
|
|
|
|
2012-07-03 01:35:10 +08:00
|
|
|
Opts.CodeCompleteOpts.IncludeMacros
|
|
|
|
= Args.hasArg(OPT_code_completion_macros);
|
|
|
|
Opts.CodeCompleteOpts.IncludeCodePatterns
|
|
|
|
= Args.hasArg(OPT_code_completion_patterns);
|
|
|
|
Opts.CodeCompleteOpts.IncludeGlobals
|
|
|
|
= !Args.hasArg(OPT_no_code_completion_globals);
|
2017-12-13 18:26:49 +08:00
|
|
|
Opts.CodeCompleteOpts.IncludeNamespaceLevelDecls
|
|
|
|
= !Args.hasArg(OPT_no_code_completion_ns_level_decls);
|
2012-07-03 01:35:10 +08:00
|
|
|
Opts.CodeCompleteOpts.IncludeBriefComments
|
|
|
|
= Args.hasArg(OPT_code_completion_brief_comments);
|
2018-05-25 20:56:26 +08:00
|
|
|
Opts.CodeCompleteOpts.IncludeFixIts
|
|
|
|
= Args.hasArg(OPT_code_completion_with_fixits);
|
2012-07-03 01:35:10 +08:00
|
|
|
|
Extend the ExternalASTSource interface to allow the AST source to
provide the layout of records, rather than letting Clang compute
the layout itself. LLDB provides the motivation for this feature:
because various layout-altering attributes (packed, aligned, etc.)
don't get reliably get placed into DWARF, the record layouts computed
by LLDB from the reconstructed records differ from the actual layouts,
and badness occurs. This interface lets the DWARF data drive layout,
so we don't need the attributes preserved to get the answer write.
The testing methodology for this change is fun. I've introduced a
variant of -fdump-record-layouts called -fdump-record-layouts-simple
that always has the simple C format and provides size/alignment/field
offsets. There is also a -cc1 option -foverride-record-layout=<file>
to take the output of -fdump-record-layouts-simple and parse it to
produce a set of overridden layouts, which is introduced into the AST
via a testing-only ExternalASTSource (called
LayoutOverrideSource). Each test contains a number of records to lay
out, which use various layout-changing attributes, and then dumps the
layouts. We then run the test again, using the preprocessor to
eliminate the layout-changing attributes entirely (which would give us
different layouts for the records), but supplying the
previously-computed record layouts. Finally, we diff the layouts
produced from the two runs to be sure that they are identical.
Note that this code makes the assumption that we don't *have* to
provide the offsets of bases or virtual bases to get the layout right,
because the alignment attributes don't affect it. I believe this
assumption holds, but if it does not, we can extend
LayoutOverrideSource to also provide base offset information.
Fixes the Clang side of <rdar://problem/10169539>.
llvm-svn: 149055
2012-01-26 15:55:45 +08:00
|
|
|
Opts.OverrideRecordLayoutsFile
|
|
|
|
= Args.getLastArgValue(OPT_foverride_record_layout_EQ);
|
2018-08-09 06:23:57 +08:00
|
|
|
Opts.AuxTriple = Args.getLastArgValue(OPT_aux_triple);
|
2016-09-27 02:53:34 +08:00
|
|
|
Opts.StatsFile = Args.getLastArgValue(OPT_stats_file);
|
2015-09-23 01:23:22 +08:00
|
|
|
|
2011-06-16 07:25:17 +08:00
|
|
|
if (const Arg *A = Args.getLastArg(OPT_arcmt_check,
|
2011-07-10 04:00:58 +08:00
|
|
|
OPT_arcmt_modify,
|
|
|
|
OPT_arcmt_migrate)) {
|
2011-06-16 07:25:17 +08:00
|
|
|
switch (A->getOption().getID()) {
|
|
|
|
default:
|
|
|
|
llvm_unreachable("missed a case");
|
|
|
|
case OPT_arcmt_check:
|
|
|
|
Opts.ARCMTAction = FrontendOptions::ARCMT_Check;
|
|
|
|
break;
|
|
|
|
case OPT_arcmt_modify:
|
|
|
|
Opts.ARCMTAction = FrontendOptions::ARCMT_Modify;
|
|
|
|
break;
|
2011-07-10 04:00:58 +08:00
|
|
|
case OPT_arcmt_migrate:
|
|
|
|
Opts.ARCMTAction = FrontendOptions::ARCMT_Migrate;
|
|
|
|
break;
|
2011-06-16 07:25:17 +08:00
|
|
|
}
|
|
|
|
}
|
2012-03-07 04:06:33 +08:00
|
|
|
Opts.MTMigrateDir = Args.getLastArgValue(OPT_mt_migrate_directory);
|
2011-07-20 01:20:03 +08:00
|
|
|
Opts.ARCMTMigrateReportOut
|
|
|
|
= Args.getLastArgValue(OPT_arcmt_migrate_report_output);
|
|
|
|
Opts.ARCMTMigrateEmitARCErrors
|
|
|
|
= Args.hasArg(OPT_arcmt_migrate_emit_arc_errors);
|
2011-06-16 07:25:17 +08:00
|
|
|
|
2012-03-07 04:06:33 +08:00
|
|
|
if (Args.hasArg(OPT_objcmt_migrate_literals))
|
|
|
|
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Literals;
|
|
|
|
if (Args.hasArg(OPT_objcmt_migrate_subscripting))
|
|
|
|
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Subscripting;
|
2014-11-01 05:19:45 +08:00
|
|
|
if (Args.hasArg(OPT_objcmt_migrate_property_dot_syntax))
|
|
|
|
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_PropertyDotSyntax;
|
2013-07-10 00:59:14 +08:00
|
|
|
if (Args.hasArg(OPT_objcmt_migrate_property))
|
|
|
|
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Property;
|
2013-08-29 07:22:46 +08:00
|
|
|
if (Args.hasArg(OPT_objcmt_migrate_readonly_property))
|
|
|
|
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_ReadonlyProperty;
|
2013-10-03 05:32:39 +08:00
|
|
|
if (Args.hasArg(OPT_objcmt_migrate_readwrite_property))
|
|
|
|
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_ReadwriteProperty;
|
2013-10-03 05:58:13 +08:00
|
|
|
if (Args.hasArg(OPT_objcmt_migrate_annotation))
|
|
|
|
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Annotation;
|
2013-11-06 06:28:30 +08:00
|
|
|
if (Args.hasArg(OPT_objcmt_returns_innerpointer_property))
|
|
|
|
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_ReturnsInnerPointerProperty;
|
2013-10-03 05:58:13 +08:00
|
|
|
if (Args.hasArg(OPT_objcmt_migrate_instancetype))
|
|
|
|
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Instancetype;
|
|
|
|
if (Args.hasArg(OPT_objcmt_migrate_nsmacros))
|
|
|
|
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_NsMacros;
|
|
|
|
if (Args.hasArg(OPT_objcmt_migrate_protocol_conformance))
|
|
|
|
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_ProtocolConformance;
|
2013-10-10 03:06:08 +08:00
|
|
|
if (Args.hasArg(OPT_objcmt_atomic_property))
|
|
|
|
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_AtomicProperty;
|
2013-11-13 08:08:36 +08:00
|
|
|
if (Args.hasArg(OPT_objcmt_ns_nonatomic_iosonly))
|
|
|
|
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty;
|
2013-12-11 02:36:49 +08:00
|
|
|
if (Args.hasArg(OPT_objcmt_migrate_designated_init))
|
|
|
|
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_DesignatedInitializer;
|
2013-10-03 05:32:39 +08:00
|
|
|
if (Args.hasArg(OPT_objcmt_migrate_all))
|
|
|
|
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_MigrateDecls;
|
2012-03-07 04:06:33 +08:00
|
|
|
|
2013-12-11 02:36:53 +08:00
|
|
|
Opts.ObjCMTWhiteListPath = Args.getLastArgValue(OPT_objcmt_whitelist_dir_path);
|
2013-11-15 00:33:29 +08:00
|
|
|
|
2012-03-07 04:06:33 +08:00
|
|
|
if (Opts.ARCMTAction != FrontendOptions::ARCMT_None &&
|
|
|
|
Opts.ObjCMTAction != FrontendOptions::ObjCMT_None) {
|
|
|
|
Diags.Report(diag::err_drv_argument_not_allowed_with)
|
|
|
|
<< "ARC migration" << "ObjC migration";
|
|
|
|
}
|
|
|
|
|
2019-08-05 21:59:26 +08:00
|
|
|
InputKind DashX(Language::Unknown);
|
2009-12-01 11:16:53 +08:00
|
|
|
if (const Arg *A = Args.getLastArg(OPT_x)) {
|
2017-04-27 02:57:40 +08:00
|
|
|
StringRef XValue = A->getValue();
|
2017-04-28 09:49:42 +08:00
|
|
|
|
|
|
|
// Parse suffixes: '<lang>(-header|[-module-map][-cpp-output])'.
|
|
|
|
// FIXME: Supporting '<lang>-header-cpp-output' would be useful.
|
|
|
|
bool Preprocessed = XValue.consume_back("-cpp-output");
|
|
|
|
bool ModuleMap = XValue.consume_back("-module-map");
|
|
|
|
IsHeaderFile =
|
|
|
|
!Preprocessed && !ModuleMap && XValue.consume_back("-header");
|
|
|
|
|
|
|
|
// Principal languages.
|
2017-04-27 02:57:40 +08:00
|
|
|
DashX = llvm::StringSwitch<InputKind>(XValue)
|
2019-08-05 21:59:26 +08:00
|
|
|
.Case("c", Language::C)
|
|
|
|
.Case("cl", Language::OpenCL)
|
|
|
|
.Case("cuda", Language::CUDA)
|
|
|
|
.Case("hip", Language::HIP)
|
|
|
|
.Case("c++", Language::CXX)
|
|
|
|
.Case("objective-c", Language::ObjC)
|
|
|
|
.Case("objective-c++", Language::ObjCXX)
|
|
|
|
.Case("renderscript", Language::RenderScript)
|
|
|
|
.Default(Language::Unknown);
|
2017-04-28 09:49:42 +08:00
|
|
|
|
|
|
|
// "objc[++]-cpp-output" is an acceptable synonym for
|
|
|
|
// "objective-c[++]-cpp-output".
|
|
|
|
if (DashX.isUnknown() && Preprocessed && !IsHeaderFile && !ModuleMap)
|
|
|
|
DashX = llvm::StringSwitch<InputKind>(XValue)
|
2019-08-05 21:59:26 +08:00
|
|
|
.Case("objc", Language::ObjC)
|
|
|
|
.Case("objc++", Language::ObjCXX)
|
|
|
|
.Default(Language::Unknown);
|
2017-04-28 09:49:42 +08:00
|
|
|
|
|
|
|
// Some special cases cannot be combined with suffixes.
|
|
|
|
if (DashX.isUnknown() && !Preprocessed && !ModuleMap && !IsHeaderFile)
|
|
|
|
DashX = llvm::StringSwitch<InputKind>(XValue)
|
2019-08-05 21:59:26 +08:00
|
|
|
.Case("cpp-output", InputKind(Language::C).getPreprocessed())
|
|
|
|
.Case("assembler-with-cpp", Language::Asm)
|
2017-04-28 09:49:42 +08:00
|
|
|
.Cases("ast", "pcm",
|
2019-08-05 21:59:26 +08:00
|
|
|
InputKind(Language::Unknown, InputKind::Precompiled))
|
|
|
|
.Case("ir", Language::LLVM_IR)
|
|
|
|
.Default(Language::Unknown);
|
2017-04-28 09:49:42 +08:00
|
|
|
|
2017-04-27 02:57:40 +08:00
|
|
|
if (DashX.isUnknown())
|
2009-12-01 11:16:53 +08:00
|
|
|
Diags.Report(diag::err_drv_invalid_value)
|
2012-11-01 12:30:05 +08:00
|
|
|
<< A->getAsString(Args) << A->getValue();
|
2017-04-27 02:57:40 +08:00
|
|
|
|
2017-04-28 09:49:42 +08:00
|
|
|
if (Preprocessed)
|
2017-04-27 02:57:40 +08:00
|
|
|
DashX = DashX.getPreprocessed();
|
2017-04-28 09:49:42 +08:00
|
|
|
if (ModuleMap)
|
|
|
|
DashX = DashX.withFormat(InputKind::ModuleMap);
|
2009-12-01 11:16:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// '-' is the default input if none is given.
|
2010-05-21 00:54:55 +08:00
|
|
|
std::vector<std::string> Inputs = Args.getAllArgValues(OPT_INPUT);
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.Inputs.clear();
|
|
|
|
if (Inputs.empty())
|
|
|
|
Inputs.push_back("-");
|
|
|
|
for (unsigned i = 0, e = Inputs.size(); i != e; ++i) {
|
2010-06-08 07:22:09 +08:00
|
|
|
InputKind IK = DashX;
|
2017-04-27 02:57:40 +08:00
|
|
|
if (IK.isUnknown()) {
|
2009-12-01 11:16:53 +08:00
|
|
|
IK = FrontendOptions::getInputKindForExtension(
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef(Inputs[i]).rsplit('.').second);
|
2017-04-27 02:57:40 +08:00
|
|
|
// FIXME: Warn on this?
|
|
|
|
if (IK.isUnknown())
|
2019-08-05 21:59:26 +08:00
|
|
|
IK = Language::C;
|
2009-12-01 11:16:53 +08:00
|
|
|
// FIXME: Remove this hack.
|
|
|
|
if (i == 0)
|
|
|
|
DashX = IK;
|
|
|
|
}
|
2017-04-28 09:49:42 +08:00
|
|
|
|
|
|
|
// The -emit-module action implicitly takes a module map.
|
|
|
|
if (Opts.ProgramAction == frontend::GenerateModule &&
|
|
|
|
IK.getFormat() == InputKind::Source)
|
|
|
|
IK = IK.withFormat(InputKind::ModuleMap);
|
|
|
|
|
2015-05-30 03:42:19 +08:00
|
|
|
Opts.Inputs.emplace_back(std::move(Inputs[i]), IK);
|
2009-12-01 11:16:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return DashX;
|
|
|
|
}
|
|
|
|
|
2009-12-15 08:06:45 +08:00
|
|
|
std::string CompilerInvocation::GetResourcesPath(const char *Argv0,
|
|
|
|
void *MainAddr) {
|
2014-12-30 05:28:15 +08:00
|
|
|
std::string ClangExecutable =
|
|
|
|
llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
|
2019-02-01 06:15:32 +08:00
|
|
|
return Driver::GetResourcesPath(ClangExecutable, CLANG_RESOURCE_DIR);
|
2009-12-01 11:16:53 +08:00
|
|
|
}
|
|
|
|
|
2017-03-15 07:07:49 +08:00
|
|
|
static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
|
|
|
|
const std::string &WorkingDir) {
|
2010-05-21 00:54:55 +08:00
|
|
|
Opts.Sysroot = Args.getLastArgValue(OPT_isysroot, "/");
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.Verbose = Args.hasArg(OPT_v);
|
2011-10-11 04:34:10 +08:00
|
|
|
Opts.UseBuiltinIncludes = !Args.hasArg(OPT_nobuiltininc);
|
2011-10-12 02:20:10 +08:00
|
|
|
Opts.UseStandardSystemIncludes = !Args.hasArg(OPT_nostdsysteminc);
|
2010-03-25 04:13:48 +08:00
|
|
|
Opts.UseStandardCXXIncludes = !Args.hasArg(OPT_nostdincxx);
|
2011-06-22 05:12:29 +08:00
|
|
|
if (const Arg *A = Args.getLastArg(OPT_stdlib_EQ))
|
2012-11-01 12:30:05 +08:00
|
|
|
Opts.UseLibcxx = (strcmp(A->getValue(), "libc++") == 0);
|
2010-05-21 00:54:55 +08:00
|
|
|
Opts.ResourceDir = Args.getLastArgValue(OPT_resource_dir);
|
2017-03-15 07:07:49 +08:00
|
|
|
|
|
|
|
// Canonicalize -fmodules-cache-path before storing it.
|
|
|
|
SmallString<128> P(Args.getLastArgValue(OPT_fmodules_cache_path));
|
|
|
|
if (!(P.empty() || llvm::sys::path::is_absolute(P))) {
|
|
|
|
if (WorkingDir.empty())
|
|
|
|
llvm::sys::fs::make_absolute(P);
|
|
|
|
else
|
|
|
|
llvm::sys::fs::make_absolute(WorkingDir, P);
|
|
|
|
}
|
|
|
|
llvm::sys::path::remove_dots(P);
|
|
|
|
Opts.ModuleCachePath = P.str();
|
|
|
|
|
2014-03-03 16:12:05 +08:00
|
|
|
Opts.ModuleUserBuildPath = Args.getLastArgValue(OPT_fmodules_user_build_path);
|
2017-08-31 14:26:43 +08:00
|
|
|
// Only the -fmodule-file=<name>=<file> form.
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *A : Args.filtered(OPT_fmodule_file)) {
|
2017-08-31 14:26:43 +08:00
|
|
|
StringRef Val = A->getValue();
|
|
|
|
if (Val.find('=') != StringRef::npos)
|
|
|
|
Opts.PrebuiltModuleFiles.insert(Val.split('='));
|
|
|
|
}
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *A : Args.filtered(OPT_fprebuilt_module_path))
|
2016-08-19 01:42:15 +08:00
|
|
|
Opts.AddPrebuiltModulePath(A->getValue());
|
2011-09-14 07:15:45 +08:00
|
|
|
Opts.DisableModuleHash = Args.hasArg(OPT_fdisable_module_hash);
|
2017-03-14 02:45:08 +08:00
|
|
|
Opts.ModulesHashContent = Args.hasArg(OPT_fmodules_hash_content);
|
2016-07-27 01:12:17 +08:00
|
|
|
Opts.ModulesValidateDiagnosticOptions =
|
|
|
|
!Args.hasArg(OPT_fmodules_disable_diagnostic_validation);
|
2015-06-16 08:08:24 +08:00
|
|
|
Opts.ImplicitModuleMaps = Args.hasArg(OPT_fimplicit_module_maps);
|
2014-12-10 11:09:48 +08:00
|
|
|
Opts.ModuleMapFileHomeIsCwd = Args.hasArg(OPT_fmodule_map_file_home_is_cwd);
|
2013-06-15 01:17:23 +08:00
|
|
|
Opts.ModuleCachePruneInterval =
|
|
|
|
getLastArgIntValue(Args, OPT_fmodules_prune_interval, 7 * 24 * 60 * 60);
|
|
|
|
Opts.ModuleCachePruneAfter =
|
|
|
|
getLastArgIntValue(Args, OPT_fmodules_prune_after, 31 * 24 * 60 * 60);
|
Add an option to allow Clang verify source files for a module only once during
the build
When Clang loads the module, it verifies the user source files that the module
was built from. If any file was changed, the module is rebuilt. There are two
problems with this:
1. correctness: we don't verify system files (there are too many of them, and
stat'ing all of them would take a lot of time);
2. performance: the same module file is verified again and again during a
single build.
This change allows the build system to optimize source file verification. The
idea is based on the fact that while the project is being built, the source
files don't change. This allows us to verify the module only once during a
single build session. The build system passes a flag,
-fbuild-session-timestamp=, to inform Clang of the time when the build started.
The build system also requests to enable this feature by passing
-fmodules-validate-once-per-build-session. If these flags are not passed, the
behavior is not changed. When Clang verifies the module the first time, it
writes out a timestamp file. Then, when Clang loads the module the second
time, it finds a timestamp file, so it can compare the verification timestamp
of the module with the time when the build started. If the verification
timestamp is too old, the module is verified again, and the timestamp file is
updated.
llvm-svn: 201224
2014-02-12 18:33:14 +08:00
|
|
|
Opts.ModulesValidateOncePerBuildSession =
|
|
|
|
Args.hasArg(OPT_fmodules_validate_once_per_build_session);
|
|
|
|
Opts.BuildSessionTimestamp =
|
|
|
|
getLastArgUInt64Value(Args, OPT_fbuild_session_timestamp, 0);
|
2014-03-12 08:06:17 +08:00
|
|
|
Opts.ModulesValidateSystemHeaders =
|
|
|
|
Args.hasArg(OPT_fmodules_validate_system_headers);
|
2015-07-17 09:19:54 +08:00
|
|
|
if (const Arg *A = Args.getLastArg(OPT_fmodule_format_EQ))
|
|
|
|
Opts.ModuleFormat = A->getValue();
|
2014-03-12 08:06:17 +08:00
|
|
|
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *A : Args.filtered(OPT_fmodules_ignore_macro)) {
|
2015-06-09 09:57:17 +08:00
|
|
|
StringRef MacroDef = A->getValue();
|
2016-10-22 05:45:01 +08:00
|
|
|
Opts.ModulesIgnoreMacros.insert(
|
|
|
|
llvm::CachedHashString(MacroDef.split('=').first));
|
2013-02-07 08:21:12 +08:00
|
|
|
}
|
|
|
|
|
2011-07-28 12:45:53 +08:00
|
|
|
// Add -I..., -F..., and -index-header-map options in order.
|
|
|
|
bool IsIndexHeaderMap = false;
|
2016-05-07 03:13:55 +08:00
|
|
|
bool IsSysrootSpecified =
|
|
|
|
Args.hasArg(OPT__sysroot_EQ) || Args.hasArg(OPT_isysroot);
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *A : Args.filtered(OPT_I, OPT_F, OPT_index_header_map)) {
|
2015-06-09 09:57:17 +08:00
|
|
|
if (A->getOption().matches(OPT_index_header_map)) {
|
2011-07-28 12:45:53 +08:00
|
|
|
// -index-header-map applies to the next -I or -F.
|
|
|
|
IsIndexHeaderMap = true;
|
|
|
|
continue;
|
|
|
|
}
|
2015-06-09 09:57:17 +08:00
|
|
|
|
|
|
|
frontend::IncludeDirGroup Group =
|
|
|
|
IsIndexHeaderMap ? frontend::IndexHeaderMap : frontend::Angled;
|
|
|
|
|
2016-05-07 03:13:55 +08:00
|
|
|
bool IsFramework = A->getOption().matches(OPT_F);
|
|
|
|
std::string Path = A->getValue();
|
|
|
|
|
|
|
|
if (IsSysrootSpecified && !IsFramework && A->getValue()[0] == '=') {
|
|
|
|
SmallString<32> Buffer;
|
|
|
|
llvm::sys::path::append(Buffer, Opts.Sysroot,
|
|
|
|
llvm::StringRef(A->getValue()).substr(1));
|
|
|
|
Path = Buffer.str();
|
|
|
|
}
|
|
|
|
|
2016-11-02 18:39:27 +08:00
|
|
|
Opts.AddPath(Path, Group, IsFramework,
|
2016-05-07 03:13:55 +08:00
|
|
|
/*IgnoreSysroot*/ true);
|
2011-07-28 12:45:53 +08:00
|
|
|
IsIndexHeaderMap = false;
|
|
|
|
}
|
2009-12-01 11:16:53 +08:00
|
|
|
|
2013-01-25 09:50:34 +08:00
|
|
|
// Add -iprefix/-iwithprefix/-iwithprefixbefore options.
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef Prefix = ""; // FIXME: This isn't the correct default prefix.
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *A :
|
2015-06-09 09:57:17 +08:00
|
|
|
Args.filtered(OPT_iprefix, OPT_iwithprefix, OPT_iwithprefixbefore)) {
|
2010-06-12 06:00:13 +08:00
|
|
|
if (A->getOption().matches(OPT_iprefix))
|
2012-11-01 12:30:05 +08:00
|
|
|
Prefix = A->getValue();
|
2010-06-12 06:00:13 +08:00
|
|
|
else if (A->getOption().matches(OPT_iwithprefix))
|
2015-06-09 09:57:17 +08:00
|
|
|
Opts.AddPath(Prefix.str() + A->getValue(), frontend::After, false, true);
|
2009-12-01 11:16:53 +08:00
|
|
|
else
|
2015-06-09 09:57:17 +08:00
|
|
|
Opts.AddPath(Prefix.str() + A->getValue(), frontend::Angled, false, true);
|
|
|
|
}
|
|
|
|
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *A : Args.filtered(OPT_idirafter))
|
2017-12-08 07:04:11 +08:00
|
|
|
Opts.AddPath(A->getValue(), frontend::After, false, true);
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *A : Args.filtered(OPT_iquote))
|
2017-12-08 07:04:11 +08:00
|
|
|
Opts.AddPath(A->getValue(), frontend::Quoted, false, true);
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *A : Args.filtered(OPT_isystem, OPT_iwithsysroot))
|
2017-12-08 07:04:11 +08:00
|
|
|
Opts.AddPath(A->getValue(), frontend::System, false,
|
|
|
|
!A->getOption().matches(OPT_iwithsysroot));
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *A : Args.filtered(OPT_iframework))
|
2017-12-08 07:04:11 +08:00
|
|
|
Opts.AddPath(A->getValue(), frontend::System, true, true);
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *A : Args.filtered(OPT_iframeworkwithsysroot))
|
2017-12-08 07:04:11 +08:00
|
|
|
Opts.AddPath(A->getValue(), frontend::System, /*IsFramework=*/true,
|
|
|
|
/*IgnoreSysRoot=*/false);
|
|
|
|
|
|
|
|
// Add the paths for the various language specific isystem flags.
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *A : Args.filtered(OPT_c_isystem))
|
2017-12-08 07:04:11 +08:00
|
|
|
Opts.AddPath(A->getValue(), frontend::CSystem, false, true);
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *A : Args.filtered(OPT_cxx_isystem))
|
2017-12-08 07:04:11 +08:00
|
|
|
Opts.AddPath(A->getValue(), frontend::CXXSystem, false, true);
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *A : Args.filtered(OPT_objc_isystem))
|
2017-12-08 07:04:11 +08:00
|
|
|
Opts.AddPath(A->getValue(), frontend::ObjCSystem, false,true);
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *A : Args.filtered(OPT_objcxx_isystem))
|
2017-12-08 07:04:11 +08:00
|
|
|
Opts.AddPath(A->getValue(), frontend::ObjCXXSystem, false, true);
|
|
|
|
|
|
|
|
// Add the internal paths from a driver that detects standard include paths.
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *A :
|
2017-12-08 07:04:11 +08:00
|
|
|
Args.filtered(OPT_internal_isystem, OPT_internal_externc_isystem)) {
|
|
|
|
frontend::IncludeDirGroup Group = frontend::System;
|
|
|
|
if (A->getOption().matches(OPT_internal_externc_isystem))
|
|
|
|
Group = frontend::ExternCSystem;
|
|
|
|
Opts.AddPath(A->getValue(), Group, false, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add the path prefixes which are implicitly treated as being system headers.
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *A :
|
2017-12-08 07:04:11 +08:00
|
|
|
Args.filtered(OPT_system_header_prefix, OPT_no_system_header_prefix))
|
|
|
|
Opts.AddSystemHeaderPrefix(
|
|
|
|
A->getValue(), A->getOption().matches(OPT_system_header_prefix));
|
|
|
|
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *A : Args.filtered(OPT_ivfsoverlay))
|
2017-12-08 07:04:11 +08:00
|
|
|
Opts.AddVFSOverlayFile(A->getValue());
|
|
|
|
}
|
|
|
|
|
|
|
|
void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
|
|
|
|
const llvm::Triple &T,
|
|
|
|
PreprocessorOptions &PPOpts,
|
|
|
|
LangStandard::Kind LangStd) {
|
|
|
|
// Set some properties which depend solely on the input kind; it would be nice
|
|
|
|
// to move these to the language standard, and have the driver resolve the
|
|
|
|
// input kind + language standard.
|
|
|
|
//
|
|
|
|
// FIXME: Perhaps a better model would be for a single source file to have
|
|
|
|
// multiple language standards (C / C++ std, ObjC std, OpenCL std, OpenMP std)
|
|
|
|
// simultaneously active?
|
2019-08-05 21:59:26 +08:00
|
|
|
if (IK.getLanguage() == Language::Asm) {
|
2017-12-08 07:04:11 +08:00
|
|
|
Opts.AsmPreprocessor = 1;
|
|
|
|
} else if (IK.isObjectiveC()) {
|
2018-10-31 04:31:30 +08:00
|
|
|
Opts.ObjC = 1;
|
2017-12-08 07:04:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (LangStd == LangStandard::lang_unspecified) {
|
|
|
|
// Based on the base language, pick one.
|
|
|
|
switch (IK.getLanguage()) {
|
2019-08-05 21:59:26 +08:00
|
|
|
case Language::Unknown:
|
|
|
|
case Language::LLVM_IR:
|
2017-12-08 07:04:11 +08:00
|
|
|
llvm_unreachable("Invalid input kind!");
|
2019-08-05 21:59:26 +08:00
|
|
|
case Language::OpenCL:
|
2017-12-08 07:04:11 +08:00
|
|
|
LangStd = LangStandard::lang_opencl10;
|
|
|
|
break;
|
2019-08-05 21:59:26 +08:00
|
|
|
case Language::CUDA:
|
2017-12-08 07:04:11 +08:00
|
|
|
LangStd = LangStandard::lang_cuda;
|
|
|
|
break;
|
2019-08-05 21:59:26 +08:00
|
|
|
case Language::Asm:
|
|
|
|
case Language::C:
|
2018-03-07 05:26:28 +08:00
|
|
|
#if defined(CLANG_DEFAULT_STD_C)
|
|
|
|
LangStd = CLANG_DEFAULT_STD_C;
|
|
|
|
#else
|
2017-12-08 07:04:11 +08:00
|
|
|
// The PS4 uses C99 as the default C standard.
|
|
|
|
if (T.isPS4())
|
|
|
|
LangStd = LangStandard::lang_gnu99;
|
|
|
|
else
|
|
|
|
LangStd = LangStandard::lang_gnu11;
|
2018-03-07 05:26:28 +08:00
|
|
|
#endif
|
2017-12-08 07:04:11 +08:00
|
|
|
break;
|
2019-08-05 21:59:26 +08:00
|
|
|
case Language::ObjC:
|
2018-03-07 05:26:28 +08:00
|
|
|
#if defined(CLANG_DEFAULT_STD_C)
|
|
|
|
LangStd = CLANG_DEFAULT_STD_C;
|
|
|
|
#else
|
2017-12-08 07:04:11 +08:00
|
|
|
LangStd = LangStandard::lang_gnu11;
|
2018-03-07 05:26:28 +08:00
|
|
|
#endif
|
2017-12-08 07:04:11 +08:00
|
|
|
break;
|
2019-08-05 21:59:26 +08:00
|
|
|
case Language::CXX:
|
|
|
|
case Language::ObjCXX:
|
2018-03-07 05:26:28 +08:00
|
|
|
#if defined(CLANG_DEFAULT_STD_CXX)
|
|
|
|
LangStd = CLANG_DEFAULT_STD_CXX;
|
|
|
|
#else
|
2017-12-09 20:09:54 +08:00
|
|
|
LangStd = LangStandard::lang_gnucxx14;
|
2018-03-07 05:26:28 +08:00
|
|
|
#endif
|
2017-12-08 07:04:11 +08:00
|
|
|
break;
|
2019-08-05 21:59:26 +08:00
|
|
|
case Language::RenderScript:
|
2017-12-08 07:04:11 +08:00
|
|
|
LangStd = LangStandard::lang_c99;
|
|
|
|
break;
|
2019-08-05 21:59:26 +08:00
|
|
|
case Language::HIP:
|
2018-04-25 09:10:37 +08:00
|
|
|
LangStd = LangStandard::lang_hip;
|
|
|
|
break;
|
2017-12-08 07:04:11 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd);
|
|
|
|
Opts.LineComment = Std.hasLineComments();
|
|
|
|
Opts.C99 = Std.isC99();
|
|
|
|
Opts.C11 = Std.isC11();
|
|
|
|
Opts.C17 = Std.isC17();
|
2019-05-14 20:09:55 +08:00
|
|
|
Opts.C2x = Std.isC2x();
|
2017-12-08 07:04:11 +08:00
|
|
|
Opts.CPlusPlus = Std.isCPlusPlus();
|
|
|
|
Opts.CPlusPlus11 = Std.isCPlusPlus11();
|
|
|
|
Opts.CPlusPlus14 = Std.isCPlusPlus14();
|
|
|
|
Opts.CPlusPlus17 = Std.isCPlusPlus17();
|
|
|
|
Opts.CPlusPlus2a = Std.isCPlusPlus2a();
|
|
|
|
Opts.Digraphs = Std.hasDigraphs();
|
|
|
|
Opts.GNUMode = Std.isGNUMode();
|
|
|
|
Opts.GNUInline = !Opts.C99 && !Opts.CPlusPlus;
|
|
|
|
Opts.HexFloats = Std.hasHexFloats();
|
|
|
|
Opts.ImplicitInt = Std.hasImplicitInt();
|
|
|
|
|
|
|
|
// Set OpenCL Version.
|
|
|
|
Opts.OpenCL = Std.isOpenCL();
|
|
|
|
if (LangStd == LangStandard::lang_opencl10)
|
|
|
|
Opts.OpenCLVersion = 100;
|
|
|
|
else if (LangStd == LangStandard::lang_opencl11)
|
|
|
|
Opts.OpenCLVersion = 110;
|
|
|
|
else if (LangStd == LangStandard::lang_opencl12)
|
|
|
|
Opts.OpenCLVersion = 120;
|
|
|
|
else if (LangStd == LangStandard::lang_opencl20)
|
|
|
|
Opts.OpenCLVersion = 200;
|
2018-04-12 22:17:04 +08:00
|
|
|
else if (LangStd == LangStandard::lang_openclcpp)
|
|
|
|
Opts.OpenCLCPlusPlusVersion = 100;
|
2017-12-08 07:04:11 +08:00
|
|
|
|
|
|
|
// OpenCL has some additional defaults.
|
|
|
|
if (Opts.OpenCL) {
|
|
|
|
Opts.AltiVec = 0;
|
|
|
|
Opts.ZVector = 0;
|
|
|
|
Opts.LaxVectorConversions = 0;
|
|
|
|
Opts.setDefaultFPContractMode(LangOptions::FPC_On);
|
|
|
|
Opts.NativeHalfType = 1;
|
|
|
|
Opts.NativeHalfArgsAndReturns = 1;
|
2018-04-23 19:23:47 +08:00
|
|
|
Opts.OpenCLCPlusPlus = Opts.CPlusPlus;
|
2019-06-19 20:48:22 +08:00
|
|
|
|
2017-12-08 07:04:11 +08:00
|
|
|
// Include default header file for OpenCL.
|
2019-06-19 20:48:22 +08:00
|
|
|
if (Opts.IncludeDefaultHeader) {
|
|
|
|
if (Opts.DeclareOpenCLBuiltins) {
|
|
|
|
// Only include base header file for builtin types and constants.
|
|
|
|
PPOpts.Includes.push_back("opencl-c-base.h");
|
|
|
|
} else {
|
|
|
|
PPOpts.Includes.push_back("opencl-c.h");
|
|
|
|
}
|
2017-12-08 07:04:11 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-05 21:59:26 +08:00
|
|
|
Opts.HIP = IK.getLanguage() == Language::HIP;
|
|
|
|
Opts.CUDA = IK.getLanguage() == Language::CUDA || Opts.HIP;
|
2017-12-08 07:04:11 +08:00
|
|
|
if (Opts.CUDA)
|
|
|
|
// Set default FP_CONTRACT to FAST.
|
|
|
|
Opts.setDefaultFPContractMode(LangOptions::FPC_Fast);
|
|
|
|
|
2019-08-05 21:59:26 +08:00
|
|
|
Opts.RenderScript = IK.getLanguage() == Language::RenderScript;
|
2017-12-08 07:04:11 +08:00
|
|
|
if (Opts.RenderScript) {
|
|
|
|
Opts.NativeHalfType = 1;
|
|
|
|
Opts.NativeHalfArgsAndReturns = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// OpenCL and C++ both have bool, true, false keywords.
|
|
|
|
Opts.Bool = Opts.OpenCL || Opts.CPlusPlus;
|
|
|
|
|
|
|
|
// OpenCL has half keyword
|
|
|
|
Opts.Half = Opts.OpenCL;
|
|
|
|
|
|
|
|
// C++ has wchar_t keyword.
|
|
|
|
Opts.WChar = Opts.CPlusPlus;
|
|
|
|
|
|
|
|
Opts.GNUKeywords = Opts.GNUMode;
|
|
|
|
Opts.CXXOperatorNames = Opts.CPlusPlus;
|
|
|
|
|
|
|
|
Opts.AlignedAllocation = Opts.CPlusPlus17;
|
|
|
|
|
|
|
|
Opts.DollarIdents = !Opts.AsmPreprocessor;
|
2019-05-14 20:09:55 +08:00
|
|
|
|
|
|
|
// Enable [[]] attributes in C++11 and C2x by default.
|
|
|
|
Opts.DoubleSquareBracketAttributes = Opts.CPlusPlus11 || Opts.C2x;
|
2017-12-08 07:04:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Attempt to parse a visibility value out of the given argument.
|
|
|
|
static Visibility parseVisibility(Arg *arg, ArgList &args,
|
|
|
|
DiagnosticsEngine &diags) {
|
|
|
|
StringRef value = arg->getValue();
|
|
|
|
if (value == "default") {
|
|
|
|
return DefaultVisibility;
|
|
|
|
} else if (value == "hidden" || value == "internal") {
|
|
|
|
return HiddenVisibility;
|
|
|
|
} else if (value == "protected") {
|
|
|
|
// FIXME: diagnose if target does not support protected visibility
|
|
|
|
return ProtectedVisibility;
|
|
|
|
}
|
|
|
|
|
|
|
|
diags.Report(diag::err_drv_invalid_value)
|
|
|
|
<< arg->getAsString(args) << value;
|
|
|
|
return DefaultVisibility;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Check if input file kind and language standard are compatible.
|
|
|
|
static bool IsInputCompatibleWithStandard(InputKind IK,
|
|
|
|
const LangStandard &S) {
|
|
|
|
switch (IK.getLanguage()) {
|
2019-08-05 21:59:26 +08:00
|
|
|
case Language::Unknown:
|
|
|
|
case Language::LLVM_IR:
|
2017-12-08 07:04:11 +08:00
|
|
|
llvm_unreachable("should not parse language flags for this input");
|
|
|
|
|
2019-08-05 21:59:26 +08:00
|
|
|
case Language::C:
|
|
|
|
case Language::ObjC:
|
|
|
|
case Language::RenderScript:
|
|
|
|
return S.getLanguage() == Language::C;
|
2017-12-08 07:04:11 +08:00
|
|
|
|
2019-08-05 21:59:26 +08:00
|
|
|
case Language::OpenCL:
|
|
|
|
return S.getLanguage() == Language::OpenCL;
|
2017-12-08 07:04:11 +08:00
|
|
|
|
2019-08-05 21:59:26 +08:00
|
|
|
case Language::CXX:
|
|
|
|
case Language::ObjCXX:
|
|
|
|
return S.getLanguage() == Language::CXX;
|
2017-04-27 02:57:40 +08:00
|
|
|
|
2019-08-05 21:59:26 +08:00
|
|
|
case Language::CUDA:
|
2017-04-27 07:44:33 +08:00
|
|
|
// FIXME: What -std= values should be permitted for CUDA compilations?
|
2019-08-05 21:59:26 +08:00
|
|
|
return S.getLanguage() == Language::CUDA ||
|
|
|
|
S.getLanguage() == Language::CXX;
|
2017-04-27 02:57:40 +08:00
|
|
|
|
2019-08-05 21:59:26 +08:00
|
|
|
case Language::HIP:
|
|
|
|
return S.getLanguage() == Language::CXX || S.getLanguage() == Language::HIP;
|
2018-04-25 09:10:37 +08:00
|
|
|
|
2019-08-05 21:59:26 +08:00
|
|
|
case Language::Asm:
|
2017-04-27 02:57:40 +08:00
|
|
|
// Accept (and ignore) all -std= values.
|
|
|
|
// FIXME: The -std= value is not ignored; it affects the tokenization
|
|
|
|
// and preprocessing rules if we're preprocessing this asm input.
|
2017-02-15 07:41:38 +08:00
|
|
|
return true;
|
2017-02-15 06:44:20 +08:00
|
|
|
}
|
2017-04-27 02:57:40 +08:00
|
|
|
|
|
|
|
llvm_unreachable("unexpected input language");
|
2017-02-15 06:44:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Get language name for given input kind.
|
|
|
|
static const StringRef GetInputKindName(InputKind IK) {
|
2017-04-27 02:57:40 +08:00
|
|
|
switch (IK.getLanguage()) {
|
2019-08-05 21:59:26 +08:00
|
|
|
case Language::C:
|
2017-04-27 07:44:33 +08:00
|
|
|
return "C";
|
2019-08-05 21:59:26 +08:00
|
|
|
case Language::ObjC:
|
2017-04-27 07:44:33 +08:00
|
|
|
return "Objective-C";
|
2019-08-05 21:59:26 +08:00
|
|
|
case Language::CXX:
|
2017-04-27 07:44:33 +08:00
|
|
|
return "C++";
|
2019-08-05 21:59:26 +08:00
|
|
|
case Language::ObjCXX:
|
2017-04-27 07:44:33 +08:00
|
|
|
return "Objective-C++";
|
2019-08-05 21:59:26 +08:00
|
|
|
case Language::OpenCL:
|
2017-02-15 06:44:20 +08:00
|
|
|
return "OpenCL";
|
2019-08-05 21:59:26 +08:00
|
|
|
case Language::CUDA:
|
2017-02-15 06:44:20 +08:00
|
|
|
return "CUDA";
|
2019-08-05 21:59:26 +08:00
|
|
|
case Language::RenderScript:
|
2017-04-27 07:44:33 +08:00
|
|
|
return "RenderScript";
|
2019-08-05 21:59:26 +08:00
|
|
|
case Language::HIP:
|
2018-04-25 09:10:37 +08:00
|
|
|
return "HIP";
|
2017-04-27 07:44:33 +08:00
|
|
|
|
2019-08-05 21:59:26 +08:00
|
|
|
case Language::Asm:
|
2017-04-27 07:44:33 +08:00
|
|
|
return "Asm";
|
2019-08-05 21:59:26 +08:00
|
|
|
case Language::LLVM_IR:
|
2017-04-27 07:44:33 +08:00
|
|
|
return "LLVM IR";
|
|
|
|
|
2019-08-05 21:59:26 +08:00
|
|
|
case Language::Unknown:
|
2017-04-27 07:44:33 +08:00
|
|
|
break;
|
2017-02-15 06:44:20 +08:00
|
|
|
}
|
2017-04-27 07:44:33 +08:00
|
|
|
llvm_unreachable("unknown input language");
|
2017-02-15 06:44:20 +08:00
|
|
|
}
|
|
|
|
|
2010-12-04 09:50:27 +08:00
|
|
|
static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
|
2016-02-08 23:59:20 +08:00
|
|
|
const TargetOptions &TargetOpts,
|
2016-06-21 03:26:00 +08:00
|
|
|
PreprocessorOptions &PPOpts,
|
2011-09-26 07:23:43 +08:00
|
|
|
DiagnosticsEngine &Diags) {
|
2010-12-04 09:50:27 +08:00
|
|
|
// FIXME: Cleanup per-file based stuff.
|
|
|
|
LangStandard::Kind LangStd = LangStandard::lang_unspecified;
|
|
|
|
if (const Arg *A = Args.getLastArg(OPT_std_EQ)) {
|
2019-08-05 21:59:26 +08:00
|
|
|
LangStd = LangStandard::getLangKind(A->getValue());
|
2017-02-15 06:44:20 +08:00
|
|
|
if (LangStd == LangStandard::lang_unspecified) {
|
2010-12-04 09:50:27 +08:00
|
|
|
Diags.Report(diag::err_drv_invalid_value)
|
2012-11-01 12:30:05 +08:00
|
|
|
<< A->getAsString(Args) << A->getValue();
|
2017-02-15 06:44:20 +08:00
|
|
|
// Report supported standards with short description.
|
|
|
|
for (unsigned KindValue = 0;
|
|
|
|
KindValue != LangStandard::lang_unspecified;
|
|
|
|
++KindValue) {
|
|
|
|
const LangStandard &Std = LangStandard::getLangStandardForKind(
|
|
|
|
static_cast<LangStandard::Kind>(KindValue));
|
|
|
|
if (IsInputCompatibleWithStandard(IK, Std)) {
|
2017-04-27 09:17:05 +08:00
|
|
|
auto Diag = Diags.Report(diag::note_drv_use_standard);
|
|
|
|
Diag << Std.getName() << Std.getDescription();
|
|
|
|
unsigned NumAliases = 0;
|
|
|
|
#define LANGSTANDARD(id, name, lang, desc, features)
|
|
|
|
#define LANGSTANDARD_ALIAS(id, alias) \
|
|
|
|
if (KindValue == LangStandard::lang_##id) ++NumAliases;
|
|
|
|
#define LANGSTANDARD_ALIAS_DEPR(id, alias)
|
2019-08-05 21:59:26 +08:00
|
|
|
#include "clang/Basic/LangStandards.def"
|
2017-04-27 09:17:05 +08:00
|
|
|
Diag << NumAliases;
|
|
|
|
#define LANGSTANDARD(id, name, lang, desc, features)
|
|
|
|
#define LANGSTANDARD_ALIAS(id, alias) \
|
|
|
|
if (KindValue == LangStandard::lang_##id) Diag << alias;
|
|
|
|
#define LANGSTANDARD_ALIAS_DEPR(id, alias)
|
2019-08-05 21:59:26 +08:00
|
|
|
#include "clang/Basic/LangStandards.def"
|
2017-02-15 06:44:20 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2013-12-06 00:25:25 +08:00
|
|
|
// Valid standard, check to make sure language and standard are
|
|
|
|
// compatible.
|
2011-05-03 03:24:53 +08:00
|
|
|
const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd);
|
2017-02-15 06:44:20 +08:00
|
|
|
if (!IsInputCompatibleWithStandard(IK, Std)) {
|
|
|
|
Diags.Report(diag::err_drv_argument_not_allowed_with)
|
|
|
|
<< A->getAsString(Args) << GetInputKindName(IK);
|
2011-05-03 03:24:53 +08:00
|
|
|
}
|
|
|
|
}
|
2010-12-04 09:50:27 +08:00
|
|
|
}
|
|
|
|
|
Add /Zc:DllexportInlines option to clang-cl
Summary:
This CL adds /Zc:DllexportInlines flag to clang-cl.
When Zc:DllexportInlines- is specified, inline class member function is not exported if the function does not have local static variables.
By not exporting inline function, code for those functions are not generated and that reduces both compile time and obj size. Also this flag does not import inline functions from dllimported class if the function does not have local static variables.
On my 24C48T windows10 machine, build performance of chrome target in chromium repository is like below.
These stats are come with 'target_cpu="x86" enable_nacl = false is_component_build=true dcheck_always_on=true` build config and applied
* https://chromium-review.googlesource.com/c/chromium/src/+/1212379
* https://chromium-review.googlesource.com/c/v8/v8/+/1186017
Below stats were taken with this patch applied on https://github.com/llvm-project/llvm-project-20170507/commit/a05115cd4c57ff76b0f529e38118765b58ed7f2e
| config | build time | speedup | build dir size |
| with patch, PCH on, debug | 1h10m0s | x1.13 | 35.6GB |
| without patch, PCH on, debug | 1h19m17s | | 49.0GB |
| with patch, PCH off, debug | 1h15m45s | x1.16 | 33.7GB |
| without patch, PCH off, debug | 1h28m10s | | 52.3GB |
| with patch, PCH on, release | 1h13m13s | x1.22 | 26.2GB |
| without patch, PCH on, release | 1h29m57s | | 37.5GB |
| with patch, PCH off, release | 1h23m38s | x1.32 | 23.7GB |
| without patch, PCH off, release | 1h50m50s | | 38.7GB |
This patch reduced obj size and the number of exported symbols largely, that improved link time too.
e.g. link time stats of blink_core.dll become like below
| | cold disk cache | warm disk cache |
| with patch, PCH on, debug | 71s | 30s |
| without patch, PCH on, debug | 111s | 48s |
This patch's implementation is based on Nico Weber's patch. I modified to support static local variable, added tests and took stats.
Bug: https://bugs.llvm.org/show_bug.cgi?id=33628
Reviewers: hans, thakis, rnk, javed.absar
Reviewed By: hans
Subscribers: kristof.beyls, smeenai, dschuff, probinson, cfe-commits, eraman
Differential Revision: https://reviews.llvm.org/D51340
llvm-svn: 346069
2018-11-03 14:45:00 +08:00
|
|
|
if (Args.hasArg(OPT_fno_dllexport_inlines))
|
|
|
|
Opts.DllExportInlines = false;
|
|
|
|
|
2018-03-17 21:31:35 +08:00
|
|
|
if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) {
|
|
|
|
StringRef Name = A->getValue();
|
|
|
|
if (Name == "full" || Name == "branch") {
|
|
|
|
Opts.CFProtectionBranch = 1;
|
|
|
|
}
|
|
|
|
}
|
2012-06-20 07:09:52 +08:00
|
|
|
// -cl-std only applies for OpenCL language standards.
|
|
|
|
// Override the -std option in this case.
|
2010-12-04 09:51:40 +08:00
|
|
|
if (const Arg *A = Args.getLastArg(OPT_cl_std_EQ)) {
|
2012-06-20 07:09:52 +08:00
|
|
|
LangStandard::Kind OpenCLLangStd
|
2017-02-15 06:44:20 +08:00
|
|
|
= llvm::StringSwitch<LangStandard::Kind>(A->getValue())
|
2017-04-27 09:17:05 +08:00
|
|
|
.Cases("cl", "CL", LangStandard::lang_opencl10)
|
2017-02-15 06:44:20 +08:00
|
|
|
.Cases("cl1.1", "CL1.1", LangStandard::lang_opencl11)
|
|
|
|
.Cases("cl1.2", "CL1.2", LangStandard::lang_opencl12)
|
|
|
|
.Cases("cl2.0", "CL2.0", LangStandard::lang_opencl20)
|
2019-07-25 19:04:29 +08:00
|
|
|
.Cases("clc++", "CLC++", LangStandard::lang_openclcpp)
|
2017-02-15 06:44:20 +08:00
|
|
|
.Default(LangStandard::lang_unspecified);
|
2015-08-05 23:08:53 +08:00
|
|
|
|
2012-06-20 07:09:52 +08:00
|
|
|
if (OpenCLLangStd == LangStandard::lang_unspecified) {
|
2010-12-04 09:51:40 +08:00
|
|
|
Diags.Report(diag::err_drv_invalid_value)
|
2017-02-15 06:44:20 +08:00
|
|
|
<< A->getAsString(Args) << A->getValue();
|
2010-12-04 09:51:40 +08:00
|
|
|
}
|
2012-06-20 07:09:52 +08:00
|
|
|
else
|
|
|
|
LangStd = OpenCLLangStd;
|
2010-12-04 09:51:40 +08:00
|
|
|
}
|
2015-08-05 23:08:53 +08:00
|
|
|
|
2016-06-21 03:26:00 +08:00
|
|
|
Opts.IncludeDefaultHeader = Args.hasArg(OPT_finclude_default_header);
|
2019-06-03 17:39:11 +08:00
|
|
|
Opts.DeclareOpenCLBuiltins = Args.hasArg(OPT_fdeclare_opencl_builtins);
|
2016-06-21 03:26:00 +08:00
|
|
|
|
2016-04-28 03:53:03 +08:00
|
|
|
llvm::Triple T(TargetOpts.Triple);
|
2016-06-21 03:26:00 +08:00
|
|
|
CompilerInvocation::setLangDefaults(Opts, IK, T, PPOpts, LangStd);
|
2010-12-04 09:50:27 +08:00
|
|
|
|
2016-07-14 05:21:05 +08:00
|
|
|
// -cl-strict-aliasing needs to emit diagnostic in the case where CL > 1.0.
|
|
|
|
// This option should be deprecated for CL > 1.0 because
|
|
|
|
// this option was added for compatibility with OpenCL 1.0.
|
|
|
|
if (Args.getLastArg(OPT_cl_strict_aliasing)
|
|
|
|
&& Opts.OpenCLVersion > 100) {
|
|
|
|
Diags.Report(diag::warn_option_invalid_ocl_version)
|
2018-05-08 21:47:43 +08:00
|
|
|
<< Opts.getOpenCLVersionTuple().getAsString()
|
|
|
|
<< Args.getLastArg(OPT_cl_strict_aliasing)->getAsString(Args);
|
2016-07-14 05:21:05 +08:00
|
|
|
}
|
|
|
|
|
2010-04-18 04:17:31 +08:00
|
|
|
// We abuse '-f[no-]gnu-keywords' to force overriding all GNU-extension
|
|
|
|
// keywords. This behavior is provided by GCC's poorly named '-fasm' flag,
|
|
|
|
// while a subset (the non-C++ GNU keywords) is provided by GCC's
|
|
|
|
// '-fgnu-keywords'. Clang conflates the two for simplicity under the single
|
|
|
|
// name, as it doesn't seem a useful distinction.
|
|
|
|
Opts.GNUKeywords = Args.hasFlag(OPT_fgnu_keywords, OPT_fno_gnu_keywords,
|
2010-12-04 09:50:27 +08:00
|
|
|
Opts.GNUKeywords);
|
2010-04-18 04:17:31 +08:00
|
|
|
|
2018-07-17 12:56:22 +08:00
|
|
|
Opts.Digraphs = Args.hasFlag(OPT_fdigraphs, OPT_fno_digraphs, Opts.Digraphs);
|
|
|
|
|
2017-05-26 00:24:49 +08:00
|
|
|
if (Args.hasArg(OPT_fno_operator_names))
|
2010-12-04 09:50:27 +08:00
|
|
|
Opts.CXXOperatorNames = 0;
|
2009-12-01 11:16:53 +08:00
|
|
|
|
2014-12-04 05:53:36 +08:00
|
|
|
if (Args.hasArg(OPT_fcuda_is_device))
|
|
|
|
Opts.CUDAIsDevice = 1;
|
|
|
|
|
2016-01-27 01:47:20 +08:00
|
|
|
if (Args.hasArg(OPT_fcuda_allow_variadic_functions))
|
|
|
|
Opts.CUDAAllowVariadicFunctions = 1;
|
|
|
|
|
2016-03-31 07:30:21 +08:00
|
|
|
if (Args.hasArg(OPT_fno_cuda_host_device_constexpr))
|
|
|
|
Opts.CUDAHostDeviceConstexpr = 0;
|
|
|
|
|
2016-05-24 04:19:56 +08:00
|
|
|
if (Opts.CUDAIsDevice && Args.hasArg(OPT_fcuda_approx_transcendentals))
|
|
|
|
Opts.CUDADeviceApproxTranscendentals = 1;
|
|
|
|
|
2018-10-03 01:48:54 +08:00
|
|
|
Opts.GPURelocatableDeviceCode = Args.hasArg(OPT_fgpu_rdc);
|
2018-02-12 18:46:45 +08:00
|
|
|
|
2018-10-31 04:31:30 +08:00
|
|
|
if (Opts.ObjC) {
|
2012-06-20 14:18:46 +08:00
|
|
|
if (Arg *arg = Args.getLastArg(OPT_fobjc_runtime_EQ)) {
|
2012-11-01 12:30:05 +08:00
|
|
|
StringRef value = arg->getValue();
|
2012-06-20 14:18:46 +08:00
|
|
|
if (Opts.ObjCRuntime.tryParse(value))
|
|
|
|
Diags.Report(diag::err_drv_unknown_objc_runtime) << value;
|
|
|
|
}
|
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
if (Args.hasArg(OPT_fobjc_gc_only))
|
2011-09-14 01:21:33 +08:00
|
|
|
Opts.setGC(LangOptions::GCOnly);
|
2011-06-16 07:02:42 +08:00
|
|
|
else if (Args.hasArg(OPT_fobjc_gc))
|
2011-09-14 01:21:33 +08:00
|
|
|
Opts.setGC(LangOptions::HybridGC);
|
2011-06-16 07:02:42 +08:00
|
|
|
else if (Args.hasArg(OPT_fobjc_arc)) {
|
|
|
|
Opts.ObjCAutoRefCount = 1;
|
2012-08-21 10:47:43 +08:00
|
|
|
if (!Opts.ObjCRuntime.allowsARC())
|
|
|
|
Diags.Report(diag::err_arc_unsupported_on_runtime);
|
Define weak and __weak to mean ARC-style weak references, even in MRC.
Previously, __weak was silently accepted and ignored in MRC mode.
That makes this a potentially source-breaking change that we have to
roll out cautiously. Accordingly, for the time being, actual support
for __weak references in MRC is experimental, and the compiler will
reject attempts to actually form such references. The intent is to
eventually enable the feature by default in all non-GC modes.
(It is, of course, incompatible with ObjC GC's interpretation of
__weak.)
If you like, you can enable this feature with
-Xclang -fobjc-weak
but like any -Xclang option, this option may be removed at any point,
e.g. if/when it is eventually enabled by default.
This patch also enables the use of the ARC __unsafe_unretained qualifier
in MRC. Unlike __weak, this is being enabled immediately. Since
variables are essentially __unsafe_unretained by default in MRC,
the only practical uses are (1) communication and (2) changing the
default behavior of by-value block capture.
As an implementation matter, this means that the ObjC ownership
qualifiers may appear in any ObjC language mode, and so this patch
removes a number of checks for getLangOpts().ObjCAutoRefCount
that were guarding the processing of these qualifiers. I don't
expect this to be a significant drain on performance; it may even
be faster to just check for these qualifiers directly on a type
(since it's probably in a register anyway) than to do N dependent
loads to grab the LangOptions.
rdar://9674298
llvm-svn: 251041
2015-10-23 02:38:17 +08:00
|
|
|
}
|
2012-08-21 10:47:43 +08:00
|
|
|
|
Define weak and __weak to mean ARC-style weak references, even in MRC.
Previously, __weak was silently accepted and ignored in MRC mode.
That makes this a potentially source-breaking change that we have to
roll out cautiously. Accordingly, for the time being, actual support
for __weak references in MRC is experimental, and the compiler will
reject attempts to actually form such references. The intent is to
eventually enable the feature by default in all non-GC modes.
(It is, of course, incompatible with ObjC GC's interpretation of
__weak.)
If you like, you can enable this feature with
-Xclang -fobjc-weak
but like any -Xclang option, this option may be removed at any point,
e.g. if/when it is eventually enabled by default.
This patch also enables the use of the ARC __unsafe_unretained qualifier
in MRC. Unlike __weak, this is being enabled immediately. Since
variables are essentially __unsafe_unretained by default in MRC,
the only practical uses are (1) communication and (2) changing the
default behavior of by-value block capture.
As an implementation matter, this means that the ObjC ownership
qualifiers may appear in any ObjC language mode, and so this patch
removes a number of checks for getLangOpts().ObjCAutoRefCount
that were guarding the processing of these qualifiers. I don't
expect this to be a significant drain on performance; it may even
be faster to just check for these qualifiers directly on a type
(since it's probably in a register anyway) than to do N dependent
loads to grab the LangOptions.
rdar://9674298
llvm-svn: 251041
2015-10-23 02:38:17 +08:00
|
|
|
// ObjCWeakRuntime tracks whether the runtime supports __weak, not
|
|
|
|
// whether the feature is actually enabled. This is predominantly
|
|
|
|
// determined by -fobjc-runtime, but we allow it to be overridden
|
|
|
|
// from the command line for testing purposes.
|
|
|
|
if (Args.hasArg(OPT_fobjc_runtime_has_weak))
|
|
|
|
Opts.ObjCWeakRuntime = 1;
|
|
|
|
else
|
|
|
|
Opts.ObjCWeakRuntime = Opts.ObjCRuntime.allowsWeak();
|
|
|
|
|
|
|
|
// ObjCWeak determines whether __weak is actually enabled.
|
2015-11-06 03:19:56 +08:00
|
|
|
// Note that we allow -fno-objc-weak to disable this even in ARC mode.
|
|
|
|
if (auto weakArg = Args.getLastArg(OPT_fobjc_weak, OPT_fno_objc_weak)) {
|
|
|
|
if (!weakArg->getOption().matches(OPT_fobjc_weak)) {
|
|
|
|
assert(!Opts.ObjCWeak);
|
|
|
|
} else if (Opts.getGC() != LangOptions::NonGC) {
|
Define weak and __weak to mean ARC-style weak references, even in MRC.
Previously, __weak was silently accepted and ignored in MRC mode.
That makes this a potentially source-breaking change that we have to
roll out cautiously. Accordingly, for the time being, actual support
for __weak references in MRC is experimental, and the compiler will
reject attempts to actually form such references. The intent is to
eventually enable the feature by default in all non-GC modes.
(It is, of course, incompatible with ObjC GC's interpretation of
__weak.)
If you like, you can enable this feature with
-Xclang -fobjc-weak
but like any -Xclang option, this option may be removed at any point,
e.g. if/when it is eventually enabled by default.
This patch also enables the use of the ARC __unsafe_unretained qualifier
in MRC. Unlike __weak, this is being enabled immediately. Since
variables are essentially __unsafe_unretained by default in MRC,
the only practical uses are (1) communication and (2) changing the
default behavior of by-value block capture.
As an implementation matter, this means that the ObjC ownership
qualifiers may appear in any ObjC language mode, and so this patch
removes a number of checks for getLangOpts().ObjCAutoRefCount
that were guarding the processing of these qualifiers. I don't
expect this to be a significant drain on performance; it may even
be faster to just check for these qualifiers directly on a type
(since it's probably in a register anyway) than to do N dependent
loads to grab the LangOptions.
rdar://9674298
llvm-svn: 251041
2015-10-23 02:38:17 +08:00
|
|
|
Diags.Report(diag::err_objc_weak_with_gc);
|
2015-11-06 03:19:56 +08:00
|
|
|
} else if (!Opts.ObjCWeakRuntime) {
|
Define weak and __weak to mean ARC-style weak references, even in MRC.
Previously, __weak was silently accepted and ignored in MRC mode.
That makes this a potentially source-breaking change that we have to
roll out cautiously. Accordingly, for the time being, actual support
for __weak references in MRC is experimental, and the compiler will
reject attempts to actually form such references. The intent is to
eventually enable the feature by default in all non-GC modes.
(It is, of course, incompatible with ObjC GC's interpretation of
__weak.)
If you like, you can enable this feature with
-Xclang -fobjc-weak
but like any -Xclang option, this option may be removed at any point,
e.g. if/when it is eventually enabled by default.
This patch also enables the use of the ARC __unsafe_unretained qualifier
in MRC. Unlike __weak, this is being enabled immediately. Since
variables are essentially __unsafe_unretained by default in MRC,
the only practical uses are (1) communication and (2) changing the
default behavior of by-value block capture.
As an implementation matter, this means that the ObjC ownership
qualifiers may appear in any ObjC language mode, and so this patch
removes a number of checks for getLangOpts().ObjCAutoRefCount
that were guarding the processing of these qualifiers. I don't
expect this to be a significant drain on performance; it may even
be faster to just check for these qualifiers directly on a type
(since it's probably in a register anyway) than to do N dependent
loads to grab the LangOptions.
rdar://9674298
llvm-svn: 251041
2015-10-23 02:38:17 +08:00
|
|
|
Diags.Report(diag::err_objc_weak_unsupported);
|
2015-11-06 03:19:56 +08:00
|
|
|
} else {
|
|
|
|
Opts.ObjCWeak = 1;
|
Define weak and __weak to mean ARC-style weak references, even in MRC.
Previously, __weak was silently accepted and ignored in MRC mode.
That makes this a potentially source-breaking change that we have to
roll out cautiously. Accordingly, for the time being, actual support
for __weak references in MRC is experimental, and the compiler will
reject attempts to actually form such references. The intent is to
eventually enable the feature by default in all non-GC modes.
(It is, of course, incompatible with ObjC GC's interpretation of
__weak.)
If you like, you can enable this feature with
-Xclang -fobjc-weak
but like any -Xclang option, this option may be removed at any point,
e.g. if/when it is eventually enabled by default.
This patch also enables the use of the ARC __unsafe_unretained qualifier
in MRC. Unlike __weak, this is being enabled immediately. Since
variables are essentially __unsafe_unretained by default in MRC,
the only practical uses are (1) communication and (2) changing the
default behavior of by-value block capture.
As an implementation matter, this means that the ObjC ownership
qualifiers may appear in any ObjC language mode, and so this patch
removes a number of checks for getLangOpts().ObjCAutoRefCount
that were guarding the processing of these qualifiers. I don't
expect this to be a significant drain on performance; it may even
be faster to just check for these qualifiers directly on a type
(since it's probably in a register anyway) than to do N dependent
loads to grab the LangOptions.
rdar://9674298
llvm-svn: 251041
2015-10-23 02:38:17 +08:00
|
|
|
}
|
2015-11-06 03:19:56 +08:00
|
|
|
} else if (Opts.ObjCAutoRefCount) {
|
|
|
|
Opts.ObjCWeak = Opts.ObjCWeakRuntime;
|
2011-06-16 07:02:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (Args.hasArg(OPT_fno_objc_infer_related_result_type))
|
|
|
|
Opts.ObjCInferRelatedResultType = 0;
|
2015-08-05 23:08:53 +08:00
|
|
|
|
2013-11-02 05:58:17 +08:00
|
|
|
if (Args.hasArg(OPT_fobjc_subscripting_legacy_runtime))
|
|
|
|
Opts.ObjCSubscriptingLegacyRuntime =
|
|
|
|
(Opts.ObjCRuntime.getKind() == ObjCRuntime::FragileMacOSX);
|
2011-06-16 07:02:42 +08:00
|
|
|
}
|
2015-08-05 23:08:53 +08:00
|
|
|
|
2015-05-14 06:07:22 +08:00
|
|
|
if (Args.hasArg(OPT_fgnu89_inline)) {
|
|
|
|
if (Opts.CPlusPlus)
|
2017-02-15 06:44:20 +08:00
|
|
|
Diags.Report(diag::err_drv_argument_not_allowed_with)
|
|
|
|
<< "-fgnu89-inline" << GetInputKindName(IK);
|
2015-05-14 06:07:22 +08:00
|
|
|
else
|
|
|
|
Opts.GNUInline = 1;
|
|
|
|
}
|
2011-06-03 00:13:27 +08:00
|
|
|
|
2011-02-04 08:01:24 +08:00
|
|
|
if (Args.hasArg(OPT_fapple_kext)) {
|
|
|
|
if (!Opts.CPlusPlus)
|
|
|
|
Diags.Report(diag::warn_c_kext);
|
|
|
|
else
|
|
|
|
Opts.AppleKext = 1;
|
|
|
|
}
|
|
|
|
|
2009-12-01 11:16:53 +08:00
|
|
|
if (Args.hasArg(OPT_print_ivar_layout))
|
|
|
|
Opts.ObjCGCBitmapPrint = 1;
|
2018-10-25 07:28:28 +08:00
|
|
|
|
2010-04-23 04:26:39 +08:00
|
|
|
if (Args.hasArg(OPT_fno_constant_cfstrings))
|
|
|
|
Opts.NoConstantCFStrings = 1;
|
2018-10-25 07:28:28 +08:00
|
|
|
if (const auto *A = Args.getLastArg(OPT_fcf_runtime_abi_EQ))
|
|
|
|
Opts.CFRuntime =
|
|
|
|
llvm::StringSwitch<LangOptions::CoreFoundationABI>(A->getValue())
|
|
|
|
.Cases("unspecified", "standalone", "objc",
|
|
|
|
LangOptions::CoreFoundationABI::ObjectiveC)
|
|
|
|
.Cases("swift", "swift-5.0",
|
|
|
|
LangOptions::CoreFoundationABI::Swift5_0)
|
|
|
|
.Case("swift-4.2", LangOptions::CoreFoundationABI::Swift4_2)
|
|
|
|
.Case("swift-4.1", LangOptions::CoreFoundationABI::Swift4_1)
|
|
|
|
.Default(LangOptions::CoreFoundationABI::ObjectiveC);
|
2009-12-01 11:16:53 +08:00
|
|
|
|
2015-07-30 22:08:36 +08:00
|
|
|
if (Args.hasArg(OPT_fzvector))
|
|
|
|
Opts.ZVector = 1;
|
|
|
|
|
2009-12-01 11:16:53 +08:00
|
|
|
if (Args.hasArg(OPT_pthread))
|
|
|
|
Opts.POSIXThreads = 1;
|
|
|
|
|
2013-02-19 09:57:35 +08:00
|
|
|
// The value-visibility mode defaults to "default".
|
|
|
|
if (Arg *visOpt = Args.getLastArg(OPT_fvisibility)) {
|
|
|
|
Opts.setValueVisibilityMode(parseVisibility(visOpt, Args, Diags));
|
|
|
|
} else {
|
|
|
|
Opts.setValueVisibilityMode(DefaultVisibility);
|
|
|
|
}
|
|
|
|
|
|
|
|
// The type-visibility mode defaults to the value-visibility mode.
|
|
|
|
if (Arg *typeVisOpt = Args.getLastArg(OPT_ftype_visibility)) {
|
|
|
|
Opts.setTypeVisibilityMode(parseVisibility(typeVisOpt, Args, Diags));
|
|
|
|
} else {
|
|
|
|
Opts.setTypeVisibilityMode(Opts.getValueVisibilityMode());
|
|
|
|
}
|
2009-12-01 11:16:53 +08:00
|
|
|
|
2010-06-16 01:05:35 +08:00
|
|
|
if (Args.hasArg(OPT_fvisibility_inlines_hidden))
|
|
|
|
Opts.InlineVisibilityHidden = 1;
|
2010-10-21 11:16:25 +08:00
|
|
|
|
2018-12-04 11:25:25 +08:00
|
|
|
if (Args.hasArg(OPT_fvisibility_global_new_delete_hidden))
|
|
|
|
Opts.GlobalAllocationFunctionVisibilityHidden = 1;
|
|
|
|
|
2019-01-29 01:12:19 +08:00
|
|
|
if (Args.hasArg(OPT_fapply_global_visibility_to_externs))
|
|
|
|
Opts.SetVisibilityForExternDecls = 1;
|
|
|
|
|
2010-09-18 02:29:54 +08:00
|
|
|
if (Args.hasArg(OPT_ftrapv)) {
|
2010-10-21 11:16:25 +08:00
|
|
|
Opts.setSignedOverflowBehavior(LangOptions::SOB_Trapping);
|
2010-09-18 02:29:54 +08:00
|
|
|
// Set the handler, if one is specified.
|
|
|
|
Opts.OverflowHandler =
|
|
|
|
Args.getLastArgValue(OPT_ftrapv_handler);
|
|
|
|
}
|
2010-06-27 05:25:03 +08:00
|
|
|
else if (Args.hasArg(OPT_fwrapv))
|
2010-10-21 11:16:25 +08:00
|
|
|
Opts.setSignedOverflowBehavior(LangOptions::SOB_Defined);
|
2009-12-01 11:16:53 +08:00
|
|
|
|
2014-12-23 02:35:03 +08:00
|
|
|
Opts.MSVCCompat = Args.hasArg(OPT_fms_compatibility);
|
|
|
|
Opts.MicrosoftExt = Opts.MSVCCompat || Args.hasArg(OPT_fms_extensions);
|
|
|
|
Opts.AsmBlocks = Args.hasArg(OPT_fasm_blocks) || Opts.MicrosoftExt;
|
2015-03-22 16:39:22 +08:00
|
|
|
Opts.MSCompatibilityVersion = 0;
|
|
|
|
if (const Arg *A = Args.getLastArg(OPT_fms_compatibility_version)) {
|
|
|
|
VersionTuple VT;
|
|
|
|
if (VT.tryParse(A->getValue()))
|
|
|
|
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
|
|
|
|
<< A->getValue();
|
|
|
|
Opts.MSCompatibilityVersion = VT.getMajor() * 10000000 +
|
|
|
|
VT.getMinor().getValueOr(0) * 100000 +
|
|
|
|
VT.getSubminor().getValueOr(0);
|
|
|
|
}
|
2014-12-23 02:35:03 +08:00
|
|
|
|
Misc typos fixes in ./lib folder
Summary: Found via `codespell -q 3 -I ../clang-whitelist.txt -L uint,importd,crasher,gonna,cant,ue,ons,orign,ned`
Reviewers: teemperor
Reviewed By: teemperor
Subscribers: teemperor, jholewinski, jvesely, nhaehnle, whisperity, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D55475
llvm-svn: 348755
2018-12-10 20:37:46 +08:00
|
|
|
// Mimicking gcc's behavior, trigraphs are only enabled if -trigraphs
|
2014-12-23 02:35:03 +08:00
|
|
|
// is specified, or -std is set to a conforming mode.
|
|
|
|
// Trigraphs are disabled by default in c++1z onwards.
|
2017-12-05 04:27:34 +08:00
|
|
|
Opts.Trigraphs = !Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus17;
|
2014-12-24 06:32:37 +08:00
|
|
|
Opts.Trigraphs =
|
|
|
|
Args.hasFlag(OPT_ftrigraphs, OPT_fno_trigraphs, Opts.Trigraphs);
|
2009-12-01 11:16:53 +08:00
|
|
|
|
2009-12-17 04:10:18 +08:00
|
|
|
Opts.DollarIdents = Args.hasFlag(OPT_fdollars_in_identifiers,
|
|
|
|
OPT_fno_dollars_in_identifiers,
|
2010-12-04 09:50:27 +08:00
|
|
|
Opts.DollarIdents);
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.PascalStrings = Args.hasArg(OPT_fpascal_strings);
|
2014-02-13 07:50:26 +08:00
|
|
|
Opts.VtorDispMode = getLastArgIntValue(Args, OPT_vtordisp_mode_EQ, 1, Diags);
|
2010-09-03 07:59:25 +08:00
|
|
|
Opts.Borland = Args.hasArg(OPT_fborland_extensions);
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.WritableStrings = Args.hasArg(OPT_fwritable_strings);
|
2011-04-23 14:30:43 +08:00
|
|
|
Opts.ConstStrings = Args.hasFlag(OPT_fconst_strings, OPT_fno_const_strings,
|
|
|
|
Opts.ConstStrings);
|
2009-12-01 11:16:53 +08:00
|
|
|
if (Args.hasArg(OPT_fno_lax_vector_conversions))
|
2010-02-07 07:23:06 +08:00
|
|
|
Opts.LaxVectorConversions = 0;
|
|
|
|
if (Args.hasArg(OPT_fno_threadsafe_statics))
|
2010-02-11 16:02:13 +08:00
|
|
|
Opts.ThreadsafeStatics = 0;
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.Exceptions = Args.hasArg(OPT_fexceptions);
|
2011-02-22 09:52:06 +08:00
|
|
|
Opts.ObjCExceptions = Args.hasArg(OPT_fobjc_exceptions);
|
2011-02-23 11:16:42 +08:00
|
|
|
Opts.CXXExceptions = Args.hasArg(OPT_fcxx_exceptions);
|
2017-11-29 15:25:12 +08:00
|
|
|
|
2018-06-05 00:07:52 +08:00
|
|
|
// -ffixed-point
|
|
|
|
Opts.FixedPoint =
|
|
|
|
Args.hasFlag(OPT_ffixed_point, OPT_fno_fixed_point, /*Default=*/false) &&
|
|
|
|
!Opts.CPlusPlus;
|
2018-06-30 01:08:19 +08:00
|
|
|
Opts.PaddingOnUnsignedFixedPoint =
|
|
|
|
Args.hasFlag(OPT_fpadding_on_unsigned_fixed_point,
|
|
|
|
OPT_fno_padding_on_unsigned_fixed_point,
|
2018-06-21 01:19:40 +08:00
|
|
|
/*Default=*/false) &&
|
|
|
|
Opts.FixedPoint;
|
2018-06-05 00:07:52 +08:00
|
|
|
|
2017-11-29 15:25:12 +08:00
|
|
|
// Handle exception personalities
|
|
|
|
Arg *A = Args.getLastArg(options::OPT_fsjlj_exceptions,
|
|
|
|
options::OPT_fseh_exceptions,
|
|
|
|
options::OPT_fdwarf_exceptions);
|
|
|
|
if (A) {
|
|
|
|
const Option &Opt = A->getOption();
|
2018-06-08 06:54:54 +08:00
|
|
|
llvm::Triple T(TargetOpts.Triple);
|
|
|
|
if (T.isWindowsMSVCEnvironment())
|
|
|
|
Diags.Report(diag::err_fe_invalid_exception_model)
|
|
|
|
<< Opt.getName() << T.str();
|
|
|
|
|
2017-11-29 15:25:12 +08:00
|
|
|
Opts.SjLjExceptions = Opt.matches(options::OPT_fsjlj_exceptions);
|
|
|
|
Opts.SEHExceptions = Opt.matches(options::OPT_fseh_exceptions);
|
|
|
|
Opts.DWARFExceptions = Opt.matches(options::OPT_fdwarf_exceptions);
|
|
|
|
}
|
|
|
|
|
2016-02-20 17:23:47 +08:00
|
|
|
Opts.ExternCNoUnwind = Args.hasArg(OPT_fexternc_nounwind);
|
2011-03-19 05:23:38 +08:00
|
|
|
Opts.TraditionalCPP = Args.hasArg(OPT_traditional_cpp);
|
2011-02-23 11:16:42 +08:00
|
|
|
|
2016-01-27 04:15:02 +08:00
|
|
|
Opts.RTTI = Opts.CPlusPlus && !Args.hasArg(OPT_fno_rtti);
|
2014-07-02 06:24:56 +08:00
|
|
|
Opts.RTTIData = Opts.RTTI && !Args.hasArg(OPT_fno_rtti_data);
|
2016-06-15 05:43:01 +08:00
|
|
|
Opts.Blocks = Args.hasArg(OPT_fblocks) || (Opts.OpenCL
|
2018-04-12 22:17:04 +08:00
|
|
|
&& Opts.OpenCLVersion == 200);
|
2011-09-10 04:41:01 +08:00
|
|
|
Opts.BlocksRuntimeOptional = Args.hasArg(OPT_fblocks_runtime_optional);
|
2019-02-24 05:06:26 +08:00
|
|
|
Opts.Coroutines = Opts.CPlusPlus2a || Args.hasArg(OPT_fcoroutines_ts);
|
2017-12-08 07:04:11 +08:00
|
|
|
|
2017-10-15 23:01:42 +08:00
|
|
|
Opts.DoubleSquareBracketAttributes =
|
|
|
|
Args.hasFlag(OPT_fdouble_square_bracket_attributes,
|
2019-05-14 20:09:55 +08:00
|
|
|
OPT_fno_double_square_bracket_attributes,
|
|
|
|
Opts.DoubleSquareBracketAttributes);
|
2017-10-15 23:01:42 +08:00
|
|
|
|
2019-04-12 05:18:23 +08:00
|
|
|
Opts.CPlusPlusModules = Opts.CPlusPlus2a;
|
2016-07-23 10:32:21 +08:00
|
|
|
Opts.ModulesTS = Args.hasArg(OPT_fmodules_ts);
|
2019-04-12 05:18:23 +08:00
|
|
|
Opts.Modules =
|
|
|
|
Args.hasArg(OPT_fmodules) || Opts.ModulesTS || Opts.CPlusPlusModules;
|
2014-04-11 19:47:45 +08:00
|
|
|
Opts.ModulesStrictDeclUse = Args.hasArg(OPT_fmodules_strict_decluse);
|
|
|
|
Opts.ModulesDeclUse =
|
|
|
|
Args.hasArg(OPT_fmodules_decluse) || Opts.ModulesStrictDeclUse;
|
2019-04-12 05:18:23 +08:00
|
|
|
// FIXME: We only need this in C++ modules / Modules TS if we might textually
|
|
|
|
// enter a different module (eg, when building a header unit).
|
2015-05-02 05:22:17 +08:00
|
|
|
Opts.ModulesLocalVisibility =
|
2019-04-12 05:18:23 +08:00
|
|
|
Args.hasArg(OPT_fmodules_local_submodule_visibility) || Opts.ModulesTS ||
|
|
|
|
Opts.CPlusPlusModules;
|
2017-04-13 04:58:33 +08:00
|
|
|
Opts.ModulesCodegen = Args.hasArg(OPT_fmodules_codegen);
|
|
|
|
Opts.ModulesDebugInfo = Args.hasArg(OPT_fmodules_debuginfo);
|
2014-04-23 20:57:01 +08:00
|
|
|
Opts.ModulesSearchAll = Opts.Modules &&
|
|
|
|
!Args.hasArg(OPT_fno_modules_search_all) &&
|
|
|
|
Args.hasArg(OPT_fmodules_search_all);
|
2014-05-07 10:25:43 +08:00
|
|
|
Opts.ModulesErrorRecovery = !Args.hasArg(OPT_fno_modules_error_recovery);
|
2015-02-20 19:44:41 +08:00
|
|
|
Opts.ImplicitModules = !Args.hasArg(OPT_fno_implicit_modules);
|
2013-09-09 17:17:24 +08:00
|
|
|
Opts.CharIsSigned = Opts.OpenCL || !Args.hasArg(OPT_fno_signed_char);
|
2012-09-06 01:30:57 +08:00
|
|
|
Opts.WChar = Opts.CPlusPlus && !Args.hasArg(OPT_fno_wchar);
|
2018-11-15 05:04:34 +08:00
|
|
|
Opts.Char8 = Args.hasFlag(OPT_fchar8__t, OPT_fno_char8__t, Opts.CPlusPlus2a);
|
2017-10-07 07:09:55 +08:00
|
|
|
if (const Arg *A = Args.getLastArg(OPT_fwchar_type_EQ)) {
|
|
|
|
Opts.WCharSize = llvm::StringSwitch<unsigned>(A->getValue())
|
|
|
|
.Case("char", 1)
|
|
|
|
.Case("short", 2)
|
|
|
|
.Case("int", 4)
|
|
|
|
.Default(0);
|
|
|
|
if (Opts.WCharSize == 0)
|
|
|
|
Diags.Report(diag::err_fe_invalid_wchar_type) << A->getValue();
|
|
|
|
}
|
|
|
|
Opts.WCharIsSigned = Args.hasFlag(OPT_fsigned_wchar, OPT_fno_signed_wchar, true);
|
2010-10-08 08:25:19 +08:00
|
|
|
Opts.ShortEnums = Args.hasArg(OPT_fshort_enums);
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.Freestanding = Args.hasArg(OPT_ffreestanding);
|
|
|
|
Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding;
|
2016-01-06 22:35:46 +08:00
|
|
|
if (!Opts.NoBuiltin)
|
|
|
|
getAllNoBuiltinFuncValues(Args, Opts.NoBuiltinFuncs);
|
2013-07-23 08:13:01 +08:00
|
|
|
Opts.NoMathBuiltin = Args.hasArg(OPT_fno_math_builtin);
|
2017-01-01 05:41:23 +08:00
|
|
|
Opts.RelaxedTemplateTemplateArgs =
|
|
|
|
Args.hasArg(OPT_frelaxed_template_template_args);
|
2015-03-20 08:31:07 +08:00
|
|
|
Opts.SizedDeallocation = Args.hasArg(OPT_fsized_deallocation);
|
2016-10-01 06:41:36 +08:00
|
|
|
Opts.AlignedAllocation =
|
|
|
|
Args.hasFlag(OPT_faligned_allocation, OPT_fno_aligned_allocation,
|
|
|
|
Opts.AlignedAllocation);
|
2017-06-30 02:48:40 +08:00
|
|
|
Opts.AlignedAllocationUnavailable =
|
|
|
|
Opts.AlignedAllocation && Args.hasArg(OPT_aligned_alloc_unavailable);
|
2016-10-01 06:41:36 +08:00
|
|
|
Opts.NewAlignOverride =
|
|
|
|
getLastArgIntValue(Args, OPT_fnew_alignment_EQ, 0, Diags);
|
|
|
|
if (Opts.NewAlignOverride && !llvm::isPowerOf2_32(Opts.NewAlignOverride)) {
|
|
|
|
Arg *A = Args.getLastArg(OPT_fnew_alignment_EQ);
|
|
|
|
Diags.Report(diag::err_fe_invalid_alignment) << A->getAsString(Args)
|
|
|
|
<< A->getValue();
|
|
|
|
Opts.NewAlignOverride = 0;
|
|
|
|
}
|
2015-05-22 09:11:10 +08:00
|
|
|
Opts.ConceptsTS = Args.hasArg(OPT_fconcepts_ts);
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions);
|
2010-04-10 03:03:51 +08:00
|
|
|
Opts.AccessControl = !Args.hasArg(OPT_fno_access_control);
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors);
|
2013-09-09 17:17:24 +08:00
|
|
|
Opts.MathErrno = !Opts.OpenCL && Args.hasArg(OPT_fmath_errno);
|
2013-06-15 01:17:23 +08:00
|
|
|
Opts.InstantiationDepth =
|
2016-08-18 05:41:45 +08:00
|
|
|
getLastArgIntValue(Args, OPT_ftemplate_depth, 1024, Diags);
|
2013-11-07 03:31:51 +08:00
|
|
|
Opts.ArrowDepth =
|
|
|
|
getLastArgIntValue(Args, OPT_foperator_arrow_depth, 256, Diags);
|
2013-06-15 01:17:23 +08:00
|
|
|
Opts.ConstexprCallDepth =
|
|
|
|
getLastArgIntValue(Args, OPT_fconstexpr_depth, 512, Diags);
|
|
|
|
Opts.ConstexprStepLimit =
|
|
|
|
getLastArgIntValue(Args, OPT_fconstexpr_steps, 1048576, Diags);
|
|
|
|
Opts.BracketDepth = getLastArgIntValue(Args, OPT_fbracket_depth, 256, Diags);
|
2011-04-23 06:18:13 +08:00
|
|
|
Opts.DelayedTemplateParsing = Args.hasArg(OPT_fdelayed_template_parsing);
|
2013-06-15 01:17:23 +08:00
|
|
|
Opts.NumLargeByValueCopy =
|
|
|
|
getLastArgIntValue(Args, OPT_Wlarge_by_value_copy_EQ, 0, Diags);
|
2011-02-01 23:15:22 +08:00
|
|
|
Opts.MSBitfields = Args.hasArg(OPT_mms_bitfields);
|
2010-05-21 00:54:55 +08:00
|
|
|
Opts.ObjCConstantStringClass =
|
|
|
|
Args.getLastArgValue(OPT_fconstant_string_class);
|
2010-12-24 05:35:43 +08:00
|
|
|
Opts.ObjCDefaultSynthProperties =
|
2013-09-28 04:21:48 +08:00
|
|
|
!Args.hasArg(OPT_disable_objc_default_synthesize_properties);
|
2012-11-16 03:02:45 +08:00
|
|
|
Opts.EncodeExtendedBlockSig =
|
|
|
|
Args.hasArg(OPT_fencode_extended_block_signature);
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls);
|
2013-06-15 01:17:23 +08:00
|
|
|
Opts.PackStruct = getLastArgIntValue(Args, OPT_fpack_struct_EQ, 0, Diags);
|
2014-08-06 02:37:48 +08:00
|
|
|
Opts.MaxTypeAlign = getLastArgIntValue(Args, OPT_fmax_type_align_EQ, 0, Diags);
|
2016-05-04 10:58:24 +08:00
|
|
|
Opts.AlignDouble = Args.hasArg(OPT_malign_double);
|
2019-07-12 10:32:15 +08:00
|
|
|
Opts.LongDoubleSize = Args.hasArg(OPT_mlong_double_128)
|
|
|
|
? 128
|
|
|
|
: Args.hasArg(OPT_mlong_double_64) ? 64 : 0;
|
2019-07-15 15:25:11 +08:00
|
|
|
Opts.PPCIEEELongDouble = Args.hasArg(OPT_mabi_EQ_ieeelongdouble);
|
2013-06-15 01:17:23 +08:00
|
|
|
Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags);
|
2019-02-18 20:39:47 +08:00
|
|
|
Opts.ROPI = Args.hasArg(OPT_fropi);
|
|
|
|
Opts.RWPI = Args.hasArg(OPT_frwpi);
|
2016-06-23 23:07:32 +08:00
|
|
|
Opts.PIE = Args.hasArg(OPT_pic_is_pie);
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.Static = Args.hasArg(OPT_static_define);
|
Extend the ExternalASTSource interface to allow the AST source to
provide the layout of records, rather than letting Clang compute
the layout itself. LLDB provides the motivation for this feature:
because various layout-altering attributes (packed, aligned, etc.)
don't get reliably get placed into DWARF, the record layouts computed
by LLDB from the reconstructed records differ from the actual layouts,
and badness occurs. This interface lets the DWARF data drive layout,
so we don't need the attributes preserved to get the answer write.
The testing methodology for this change is fun. I've introduced a
variant of -fdump-record-layouts called -fdump-record-layouts-simple
that always has the simple C format and provides size/alignment/field
offsets. There is also a -cc1 option -foverride-record-layout=<file>
to take the output of -fdump-record-layouts-simple and parse it to
produce a set of overridden layouts, which is introduced into the AST
via a testing-only ExternalASTSource (called
LayoutOverrideSource). Each test contains a number of records to lay
out, which use various layout-changing attributes, and then dumps the
layouts. We then run the test again, using the preprocessor to
eliminate the layout-changing attributes entirely (which would give us
different layouts for the records), but supplying the
previously-computed record layouts. Finally, we diff the layouts
produced from the two runs to be sure that they are identical.
Note that this code makes the assumption that we don't *have* to
provide the offsets of bases or virtual bases to get the layout right,
because the alignment attributes don't affect it. I believe this
assumption holds, but if it does not, we can extend
LayoutOverrideSource to also provide base offset information.
Fixes the Clang side of <rdar://problem/10169539>.
llvm-svn: 149055
2012-01-26 15:55:45 +08:00
|
|
|
Opts.DumpRecordLayoutsSimple = Args.hasArg(OPT_fdump_record_layouts_simple);
|
2015-08-05 23:08:53 +08:00
|
|
|
Opts.DumpRecordLayouts = Opts.DumpRecordLayoutsSimple
|
Extend the ExternalASTSource interface to allow the AST source to
provide the layout of records, rather than letting Clang compute
the layout itself. LLDB provides the motivation for this feature:
because various layout-altering attributes (packed, aligned, etc.)
don't get reliably get placed into DWARF, the record layouts computed
by LLDB from the reconstructed records differ from the actual layouts,
and badness occurs. This interface lets the DWARF data drive layout,
so we don't need the attributes preserved to get the answer write.
The testing methodology for this change is fun. I've introduced a
variant of -fdump-record-layouts called -fdump-record-layouts-simple
that always has the simple C format and provides size/alignment/field
offsets. There is also a -cc1 option -foverride-record-layout=<file>
to take the output of -fdump-record-layouts-simple and parse it to
produce a set of overridden layouts, which is introduced into the AST
via a testing-only ExternalASTSource (called
LayoutOverrideSource). Each test contains a number of records to lay
out, which use various layout-changing attributes, and then dumps the
layouts. We then run the test again, using the preprocessor to
eliminate the layout-changing attributes entirely (which would give us
different layouts for the records), but supplying the
previously-computed record layouts. Finally, we diff the layouts
produced from the two runs to be sure that they are identical.
Note that this code makes the assumption that we don't *have* to
provide the offsets of bases or virtual bases to get the layout right,
because the alignment attributes don't affect it. I believe this
assumption holds, but if it does not, we can extend
LayoutOverrideSource to also provide base offset information.
Fixes the Clang side of <rdar://problem/10169539>.
llvm-svn: 149055
2012-01-26 15:55:45 +08:00
|
|
|
|| Args.hasArg(OPT_fdump_record_layouts);
|
2010-04-18 04:15:18 +08:00
|
|
|
Opts.DumpVTableLayouts = Args.hasArg(OPT_fdump_vtable_layouts);
|
2010-07-10 01:35:33 +08:00
|
|
|
Opts.SpellChecking = !Args.hasArg(OPT_fno_spell_checking);
|
2010-04-15 23:06:22 +08:00
|
|
|
Opts.NoBitFieldTypeAlign = Args.hasArg(OPT_fno_bitfield_type_align);
|
2010-12-04 09:50:56 +08:00
|
|
|
Opts.SinglePrecisionConstants = Args.hasArg(OPT_cl_single_precision_constant);
|
2010-12-04 09:51:23 +08:00
|
|
|
Opts.FastRelaxedMath = Args.hasArg(OPT_cl_fast_relaxed_math);
|
2011-12-13 05:14:55 +08:00
|
|
|
Opts.HexagonQdsp6Compat = Args.hasArg(OPT_mqdsp6_compat);
|
2011-03-19 06:38:29 +08:00
|
|
|
Opts.FakeAddressSpaceMap = Args.hasArg(OPT_ffake_address_space_map);
|
2011-04-10 06:50:59 +08:00
|
|
|
Opts.ParseUnknownAnytype = Args.hasArg(OPT_funknown_anytype);
|
2011-07-14 01:56:40 +08:00
|
|
|
Opts.DebuggerSupport = Args.hasArg(OPT_fdebugger_support);
|
2012-02-04 09:29:37 +08:00
|
|
|
Opts.DebuggerCastResultToId = Args.hasArg(OPT_fdebugger_cast_result_to_id);
|
2012-03-07 04:06:33 +08:00
|
|
|
Opts.DebuggerObjCLiteral = Args.hasArg(OPT_fdebugger_objc_literal);
|
2011-11-02 09:53:16 +08:00
|
|
|
Opts.ApplePragmaPack = Args.hasArg(OPT_fapple_pragma_pack);
|
2018-03-21 06:36:39 +08:00
|
|
|
Opts.ModuleName = Args.getLastArgValue(OPT_fmodule_name_EQ);
|
|
|
|
Opts.CurrentModule = Opts.ModuleName;
|
2015-03-03 03:01:14 +08:00
|
|
|
Opts.AppExt = Args.hasArg(OPT_fapplication_extension);
|
2015-02-03 05:56:15 +08:00
|
|
|
Opts.ModuleFeatures = Args.getAllArgValues(OPT_fmodule_feature);
|
2018-10-01 05:41:11 +08:00
|
|
|
llvm::sort(Opts.ModuleFeatures);
|
2015-05-15 07:44:18 +08:00
|
|
|
Opts.NativeHalfType |= Args.hasArg(OPT_fnative_half_type);
|
2016-03-19 00:58:36 +08:00
|
|
|
Opts.NativeHalfArgsAndReturns |= Args.hasArg(OPT_fnative_half_arguments_and_returns);
|
|
|
|
// Enable HalfArgsAndReturns if present in Args or if NativeHalfArgsAndReturns
|
|
|
|
// is enabled.
|
|
|
|
Opts.HalfArgsAndReturns = Args.hasArg(OPT_fallow_half_arguments_and_returns)
|
|
|
|
| Opts.NativeHalfArgsAndReturns;
|
2015-01-17 07:05:28 +08:00
|
|
|
Opts.GNUAsm = !Args.hasArg(OPT_fno_gnu_inline_asm);
|
2019-05-21 22:21:26 +08:00
|
|
|
Opts.Cmse = Args.hasArg(OPT_mcmse); // Armv8-M Security Extensions
|
2014-07-23 23:30:23 +08:00
|
|
|
|
2015-10-05 01:51:05 +08:00
|
|
|
// __declspec is enabled by default for the PS4 by the driver, and also
|
|
|
|
// enabled for Microsoft Extensions or Borland Extensions, here.
|
|
|
|
//
|
|
|
|
// FIXME: __declspec is also currently enabled for CUDA, but isn't really a
|
2016-10-09 06:16:08 +08:00
|
|
|
// CUDA extension. However, it is required for supporting
|
|
|
|
// __clang_cuda_builtin_vars.h, which uses __declspec(property). Once that has
|
|
|
|
// been rewritten in terms of something more generic, remove the Opts.CUDA
|
|
|
|
// term here.
|
2015-10-05 01:51:05 +08:00
|
|
|
Opts.DeclSpecKeyword =
|
|
|
|
Args.hasFlag(OPT_fdeclspec, OPT_fno_declspec,
|
|
|
|
(Opts.MicrosoftExt || Opts.Borland || Opts.CUDA));
|
|
|
|
|
2013-09-13 20:04:22 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_faddress_space_map_mangling_EQ)) {
|
|
|
|
switch (llvm::StringSwitch<unsigned>(A->getValue())
|
|
|
|
.Case("target", LangOptions::ASMM_Target)
|
|
|
|
.Case("no", LangOptions::ASMM_Off)
|
|
|
|
.Case("yes", LangOptions::ASMM_On)
|
|
|
|
.Default(255)) {
|
|
|
|
default:
|
2015-08-05 23:08:53 +08:00
|
|
|
Diags.Report(diag::err_drv_invalid_value)
|
2013-09-13 20:04:22 +08:00
|
|
|
<< "-faddress-space-map-mangling=" << A->getValue();
|
|
|
|
break;
|
|
|
|
case LangOptions::ASMM_Target:
|
|
|
|
Opts.setAddressSpaceMapMangling(LangOptions::ASMM_Target);
|
|
|
|
break;
|
|
|
|
case LangOptions::ASMM_On:
|
|
|
|
Opts.setAddressSpaceMapMangling(LangOptions::ASMM_On);
|
|
|
|
break;
|
|
|
|
case LangOptions::ASMM_Off:
|
|
|
|
Opts.setAddressSpaceMapMangling(LangOptions::ASMM_Off);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-12 05:05:00 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_fms_memptr_rep_EQ)) {
|
|
|
|
LangOptions::PragmaMSPointersToMembersKind InheritanceModel =
|
|
|
|
llvm::StringSwitch<LangOptions::PragmaMSPointersToMembersKind>(
|
|
|
|
A->getValue())
|
|
|
|
.Case("single",
|
|
|
|
LangOptions::PPTMK_FullGeneralitySingleInheritance)
|
|
|
|
.Case("multiple",
|
|
|
|
LangOptions::PPTMK_FullGeneralityMultipleInheritance)
|
|
|
|
.Case("virtual",
|
|
|
|
LangOptions::PPTMK_FullGeneralityVirtualInheritance)
|
|
|
|
.Default(LangOptions::PPTMK_BestCase);
|
|
|
|
if (InheritanceModel == LangOptions::PPTMK_BestCase)
|
|
|
|
Diags.Report(diag::err_drv_invalid_value)
|
|
|
|
<< "-fms-memptr-rep=" << A->getValue();
|
|
|
|
|
|
|
|
Opts.setMSPointerToMemberRepresentationMethod(InheritanceModel);
|
|
|
|
}
|
|
|
|
|
2016-05-18 17:06:38 +08:00
|
|
|
// Check for MS default calling conventions being specified.
|
|
|
|
if (Arg *A = Args.getLastArg(OPT_fdefault_calling_conv_EQ)) {
|
|
|
|
LangOptions::DefaultCallingConvention DefaultCC =
|
2017-11-03 05:08:00 +08:00
|
|
|
llvm::StringSwitch<LangOptions::DefaultCallingConvention>(A->getValue())
|
2016-05-18 17:06:38 +08:00
|
|
|
.Case("cdecl", LangOptions::DCC_CDecl)
|
|
|
|
.Case("fastcall", LangOptions::DCC_FastCall)
|
|
|
|
.Case("stdcall", LangOptions::DCC_StdCall)
|
|
|
|
.Case("vectorcall", LangOptions::DCC_VectorCall)
|
2017-11-03 05:08:00 +08:00
|
|
|
.Case("regcall", LangOptions::DCC_RegCall)
|
2016-05-18 17:06:38 +08:00
|
|
|
.Default(LangOptions::DCC_None);
|
|
|
|
if (DefaultCC == LangOptions::DCC_None)
|
|
|
|
Diags.Report(diag::err_drv_invalid_value)
|
|
|
|
<< "-fdefault-calling-conv=" << A->getValue();
|
|
|
|
|
|
|
|
llvm::Triple T(TargetOpts.Triple);
|
|
|
|
llvm::Triple::ArchType Arch = T.getArch();
|
|
|
|
bool emitError = (DefaultCC == LangOptions::DCC_FastCall ||
|
2017-05-31 23:39:28 +08:00
|
|
|
DefaultCC == LangOptions::DCC_StdCall) &&
|
|
|
|
Arch != llvm::Triple::x86;
|
2017-11-03 05:08:00 +08:00
|
|
|
emitError |= (DefaultCC == LangOptions::DCC_VectorCall ||
|
|
|
|
DefaultCC == LangOptions::DCC_RegCall) &&
|
2016-05-18 17:06:38 +08:00
|
|
|
!(Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64);
|
|
|
|
if (emitError)
|
|
|
|
Diags.Report(diag::err_drv_argument_not_allowed_with)
|
|
|
|
<< A->getSpelling() << T.getTriple();
|
|
|
|
else
|
|
|
|
Opts.setDefaultCallingConv(DefaultCC);
|
|
|
|
}
|
|
|
|
|
|
|
|
// -mrtd option
|
|
|
|
if (Arg *A = Args.getLastArg(OPT_mrtd)) {
|
|
|
|
if (Opts.getDefaultCallingConv() != LangOptions::DCC_None)
|
|
|
|
Diags.Report(diag::err_drv_argument_not_allowed_with)
|
|
|
|
<< A->getSpelling() << "-fdefault-calling-conv";
|
|
|
|
else {
|
|
|
|
llvm::Triple T(TargetOpts.Triple);
|
|
|
|
if (T.getArch() != llvm::Triple::x86)
|
|
|
|
Diags.Report(diag::err_drv_argument_not_allowed_with)
|
|
|
|
<< A->getSpelling() << T.getTriple();
|
|
|
|
else
|
|
|
|
Opts.setDefaultCallingConv(LangOptions::DCC_StdCall);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-07 22:39:17 +08:00
|
|
|
// Check if -fopenmp is specified and set default version to 4.5.
|
|
|
|
Opts.OpenMP = Args.hasArg(options::OPT_fopenmp) ? 45 : 0;
|
2017-12-30 01:36:15 +08:00
|
|
|
// Check if -fopenmp-simd is specified.
|
2018-05-22 00:40:32 +08:00
|
|
|
bool IsSimdSpecified =
|
|
|
|
Args.hasFlag(options::OPT_fopenmp_simd, options::OPT_fno_openmp_simd,
|
|
|
|
/*Default=*/false);
|
|
|
|
Opts.OpenMPSimd = !Opts.OpenMP && IsSimdSpecified;
|
2015-07-14 06:54:53 +08:00
|
|
|
Opts.OpenMPUseTLS =
|
|
|
|
Opts.OpenMP && !Args.hasArg(options::OPT_fnoopenmp_use_tls);
|
2016-01-06 21:42:12 +08:00
|
|
|
Opts.OpenMPIsDevice =
|
|
|
|
Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_is_device);
|
2018-07-26 23:17:38 +08:00
|
|
|
bool IsTargetSpecified =
|
|
|
|
Opts.OpenMPIsDevice || Args.hasArg(options::OPT_fopenmp_targets_EQ);
|
2016-01-06 21:42:12 +08:00
|
|
|
|
2017-12-30 01:36:15 +08:00
|
|
|
if (Opts.OpenMP || Opts.OpenMPSimd) {
|
2018-07-26 23:17:38 +08:00
|
|
|
if (int Version = getLastArgIntValue(
|
|
|
|
Args, OPT_fopenmp_version_EQ,
|
|
|
|
(IsSimdSpecified || IsTargetSpecified) ? 45 : Opts.OpenMP, Diags))
|
2016-05-26 19:10:11 +08:00
|
|
|
Opts.OpenMP = Version;
|
2018-07-26 23:17:38 +08:00
|
|
|
else if (IsSimdSpecified || IsTargetSpecified)
|
2017-12-30 01:36:15 +08:00
|
|
|
Opts.OpenMP = 45;
|
2016-05-26 19:10:11 +08:00
|
|
|
// Provide diagnostic when a given target is not expected to be an OpenMP
|
|
|
|
// device or host.
|
|
|
|
if (!Opts.OpenMPIsDevice) {
|
|
|
|
switch (T.getArch()) {
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
// Add unsupported host targets here:
|
|
|
|
case llvm::Triple::nvptx:
|
|
|
|
case llvm::Triple::nvptx64:
|
2018-03-27 05:45:04 +08:00
|
|
|
Diags.Report(diag::err_drv_omp_host_target_not_supported)
|
2016-05-26 19:10:11 +08:00
|
|
|
<< TargetOpts.Triple;
|
|
|
|
break;
|
|
|
|
}
|
2016-02-08 23:59:20 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[OpenMP] Prevent emission of exception handling code when using OpenMP to offload to NVIDIA devices.
Summary: For the OpenMP toolchain which offloads to NVIDIA GPUs make sure that no exception handling code is emitted.
Reviewers: arpith-jacob, sfantao, caomhin, carlo.bertolli, ABataev, Hahnfeld, hfinkel, tstellar
Reviewed By: ABataev, Hahnfeld
Subscribers: rengolin, Hahnfeld, cfe-commits
Differential Revision: https://reviews.llvm.org/D29904
llvm-svn: 310306
2017-08-08 04:57:59 +08:00
|
|
|
// Set the flag to prevent the implementation from emitting device exception
|
|
|
|
// handling code for those requiring so.
|
[OpenCL] Restrict various keywords in OpenCL C++ mode
Restrict the following keywords in the OpenCL C++ language mode,
according to Sections 2.2 & 2.9 of the OpenCL C++ 1.0 Specification.
- dynamic_cast
- typeid
- register (already restricted in OpenCL C, update the diagnostic)
- thread_local
- exceptions (try/catch/throw)
- access qualifiers read_only, write_only, read_write
Support the `__global`, `__local`, `__constant`, `__private`, and
`__generic` keywords in OpenCL C++. Leave the unprefixed address
space qualifiers such as global available, i.e., do not mark them as
reserved keywords in OpenCL C++. libclcxx provides explicit address
space pointer classes such as `global_ptr` and `global<T>` that are
implemented using the `__`-prefixed qualifiers.
Differential Revision: https://reviews.llvm.org/D46022
llvm-svn: 331874
2018-05-09 21:16:17 +08:00
|
|
|
if ((Opts.OpenMPIsDevice && T.isNVPTX()) || Opts.OpenCLCPlusPlus) {
|
[OpenMP] Prevent emission of exception handling code when using OpenMP to offload to NVIDIA devices.
Summary: For the OpenMP toolchain which offloads to NVIDIA GPUs make sure that no exception handling code is emitted.
Reviewers: arpith-jacob, sfantao, caomhin, carlo.bertolli, ABataev, Hahnfeld, hfinkel, tstellar
Reviewed By: ABataev, Hahnfeld
Subscribers: rengolin, Hahnfeld, cfe-commits
Differential Revision: https://reviews.llvm.org/D29904
llvm-svn: 310306
2017-08-08 04:57:59 +08:00
|
|
|
Opts.Exceptions = 0;
|
|
|
|
Opts.CXXExceptions = 0;
|
|
|
|
}
|
2018-11-02 22:54:07 +08:00
|
|
|
if (Opts.OpenMPIsDevice && T.isNVPTX()) {
|
|
|
|
Opts.OpenMPCUDANumSMs =
|
|
|
|
getLastArgIntValue(Args, options::OPT_fopenmp_cuda_number_of_sm_EQ,
|
|
|
|
Opts.OpenMPCUDANumSMs, Diags);
|
|
|
|
Opts.OpenMPCUDABlocksPerSM =
|
|
|
|
getLastArgIntValue(Args, options::OPT_fopenmp_cuda_blocks_per_sm_EQ,
|
|
|
|
Opts.OpenMPCUDABlocksPerSM, Diags);
|
2019-02-21 00:36:22 +08:00
|
|
|
Opts.OpenMPCUDAReductionBufNum = getLastArgIntValue(
|
|
|
|
Args, options::OPT_fopenmp_cuda_teams_reduction_recs_num_EQ,
|
|
|
|
Opts.OpenMPCUDAReductionBufNum, Diags);
|
2018-11-02 22:54:07 +08:00
|
|
|
}
|
[OpenMP] Prevent emission of exception handling code when using OpenMP to offload to NVIDIA devices.
Summary: For the OpenMP toolchain which offloads to NVIDIA GPUs make sure that no exception handling code is emitted.
Reviewers: arpith-jacob, sfantao, caomhin, carlo.bertolli, ABataev, Hahnfeld, hfinkel, tstellar
Reviewed By: ABataev, Hahnfeld
Subscribers: rengolin, Hahnfeld, cfe-commits
Differential Revision: https://reviews.llvm.org/D29904
llvm-svn: 310306
2017-08-08 04:57:59 +08:00
|
|
|
|
2019-01-10 04:38:35 +08:00
|
|
|
// Prevent auto-widening the representation of loop counters during an
|
|
|
|
// OpenMP collapse clause.
|
|
|
|
Opts.OpenMPOptimisticCollapse =
|
|
|
|
Args.hasArg(options::OPT_fopenmp_optimistic_collapse) ? 1 : 0;
|
|
|
|
|
2016-01-06 21:42:12 +08:00
|
|
|
// Get the OpenMP target triples if any.
|
2016-07-01 05:22:08 +08:00
|
|
|
if (Arg *A = Args.getLastArg(options::OPT_fopenmp_targets_EQ)) {
|
2016-01-06 21:42:12 +08:00
|
|
|
|
|
|
|
for (unsigned i = 0; i < A->getNumValues(); ++i) {
|
|
|
|
llvm::Triple TT(A->getValue(i));
|
|
|
|
|
2017-08-08 05:11:10 +08:00
|
|
|
if (TT.getArch() == llvm::Triple::UnknownArch ||
|
|
|
|
!(TT.getArch() == llvm::Triple::ppc ||
|
|
|
|
TT.getArch() == llvm::Triple::ppc64 ||
|
|
|
|
TT.getArch() == llvm::Triple::ppc64le ||
|
|
|
|
TT.getArch() == llvm::Triple::nvptx ||
|
|
|
|
TT.getArch() == llvm::Triple::nvptx64 ||
|
|
|
|
TT.getArch() == llvm::Triple::x86 ||
|
|
|
|
TT.getArch() == llvm::Triple::x86_64))
|
2018-03-27 05:45:04 +08:00
|
|
|
Diags.Report(diag::err_drv_invalid_omp_target) << A->getValue(i);
|
2016-01-06 21:42:12 +08:00
|
|
|
else
|
|
|
|
Opts.OMPTargetTriples.push_back(TT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get OpenMP host file path if any and report if a non existent file is
|
|
|
|
// found
|
2016-07-01 05:22:08 +08:00
|
|
|
if (Arg *A = Args.getLastArg(options::OPT_fopenmp_host_ir_file_path)) {
|
2016-01-06 21:42:12 +08:00
|
|
|
Opts.OMPHostIRFile = A->getValue();
|
|
|
|
if (!llvm::sys::fs::exists(Opts.OMPHostIRFile))
|
2018-03-27 05:45:04 +08:00
|
|
|
Diags.Report(diag::err_drv_omp_host_ir_file_not_found)
|
2016-01-06 21:42:12 +08:00
|
|
|
<< Opts.OMPHostIRFile;
|
|
|
|
}
|
2013-01-15 14:45:29 +08:00
|
|
|
|
2019-02-25 19:48:48 +08:00
|
|
|
Opts.SYCLIsDevice = Args.hasArg(options::OPT_fsycl_is_device);
|
|
|
|
|
2018-08-30 22:45:24 +08:00
|
|
|
// Set CUDA mode for OpenMP target NVPTX if specified in options
|
2018-03-01 04:48:35 +08:00
|
|
|
Opts.OpenMPCUDAMode = Opts.OpenMPIsDevice && T.isNVPTX() &&
|
|
|
|
Args.hasArg(options::OPT_fopenmp_cuda_mode);
|
|
|
|
|
2018-08-30 22:45:24 +08:00
|
|
|
// Set CUDA mode for OpenMP target NVPTX if specified in options
|
|
|
|
Opts.OpenMPCUDAForceFullRuntime =
|
|
|
|
Opts.OpenMPIsDevice && T.isNVPTX() &&
|
|
|
|
Args.hasArg(options::OPT_fopenmp_cuda_force_full_runtime);
|
|
|
|
|
2011-04-23 17:27:53 +08:00
|
|
|
// Record whether the __DEPRECATED define was requested.
|
|
|
|
Opts.Deprecated = Args.hasFlag(OPT_fdeprecated_macro,
|
|
|
|
OPT_fno_deprecated_macro,
|
|
|
|
Opts.Deprecated);
|
|
|
|
|
2009-12-01 11:16:53 +08:00
|
|
|
// FIXME: Eliminate this dependency.
|
2012-08-09 00:09:15 +08:00
|
|
|
unsigned Opt = getOptimizationLevel(Args, IK, Diags),
|
2013-04-11 05:30:03 +08:00
|
|
|
OptSize = getOptimizationLevelSize(Args);
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.Optimize = Opt != 0;
|
2012-08-09 00:09:15 +08:00
|
|
|
Opts.OptimizeSize = OptSize != 0;
|
2009-12-01 11:16:53 +08:00
|
|
|
|
|
|
|
// This is the __NO_INLINE__ define, which just depends on things like the
|
|
|
|
// optimization level and -fno-inline, not actually whether the backend has
|
|
|
|
// inlining enabled.
|
Cleanup the handling of noinline function attributes, -fno-inline,
-fno-inline-functions, -O0, and optnone.
These were really, really tangled together:
- We used the noinline LLVM attribute for -fno-inline
- But not for -fno-inline-functions (breaking LTO)
- But we did use it for -finline-hint-functions (yay, LTO is happy!)
- But we didn't for -O0 (LTO is sad yet again...)
- We had weird structuring of CodeGenOpts with both an inlining
enumeration and a boolean. They interacted in weird ways and
needlessly.
- A *lot* of set smashing went on with setting these, and then got worse
when we considered optnone and other inlining-effecting attributes.
- A bunch of inline affecting attributes were managed in a completely
different place from -fno-inline.
- Even with -fno-inline we failed to put the LLVM noinline attribute
onto many generated function definitions because they didn't show up
as AST-level functions.
- If you passed -O0 but -finline-functions we would run the normal
inliner pass in LLVM despite it being in the O0 pipeline, which really
doesn't make much sense.
- Lastly, we used things like '-fno-inline' to manipulate the pass
pipeline which forced the pass pipeline to be much more
parameterizable than it really needs to be. Instead we can *just* use
the optimization level to select a pipeline and control the rest via
attributes.
Sadly, this causes a bunch of churn in tests because we don't run the
optimizer in the tests and check the contents of attribute sets. It
would be awesome if attribute sets were a bit more FileCheck friendly,
but oh well.
I think this is a significant improvement and should remove the semantic
need to change what inliner pass we run in order to comply with the
requested inlining semantics by relying completely on attributes. It
also cleans up tho optnone and related handling a bit.
One unfortunate aspect of this is that for generating alwaysinline
routines like those in OpenMP we end up removing noinline and then
adding alwaysinline. I tried a bunch of other approaches, but because we
recompute function attributes from scratch and don't have a declaration
here I couldn't find anything substantially cleaner than this.
Differential Revision: https://reviews.llvm.org/D28053
llvm-svn: 290398
2016-12-23 09:24:49 +08:00
|
|
|
Opts.NoInlineDefine = !Opts.Optimize;
|
|
|
|
if (Arg *InlineArg = Args.getLastArg(
|
|
|
|
options::OPT_finline_functions, options::OPT_finline_hint_functions,
|
|
|
|
options::OPT_fno_inline_functions, options::OPT_fno_inline))
|
|
|
|
if (InlineArg->getOption().matches(options::OPT_fno_inline))
|
|
|
|
Opts.NoInlineDefine = true;
|
2009-12-01 11:16:53 +08:00
|
|
|
|
2014-12-11 00:41:14 +08:00
|
|
|
Opts.FastMath = Args.hasArg(OPT_ffast_math) ||
|
|
|
|
Args.hasArg(OPT_cl_fast_relaxed_math);
|
|
|
|
Opts.FiniteMathOnly = Args.hasArg(OPT_ffinite_math_only) ||
|
|
|
|
Args.hasArg(OPT_cl_finite_math_only) ||
|
|
|
|
Args.hasArg(OPT_cl_fast_relaxed_math);
|
2015-10-02 22:56:37 +08:00
|
|
|
Opts.UnsafeFPMath = Args.hasArg(OPT_menable_unsafe_fp_math) ||
|
|
|
|
Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
|
|
|
|
Args.hasArg(OPT_cl_fast_relaxed_math);
|
2012-01-02 22:19:45 +08:00
|
|
|
|
2017-03-30 05:54:24 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_ffp_contract)) {
|
|
|
|
StringRef Val = A->getValue();
|
|
|
|
if (Val == "fast")
|
|
|
|
Opts.setDefaultFPContractMode(LangOptions::FPC_Fast);
|
|
|
|
else if (Val == "on")
|
|
|
|
Opts.setDefaultFPContractMode(LangOptions::FPC_On);
|
|
|
|
else if (Val == "off")
|
|
|
|
Opts.setDefaultFPContractMode(LangOptions::FPC_Off);
|
|
|
|
else
|
|
|
|
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
|
|
|
|
}
|
|
|
|
|
2012-09-13 14:41:18 +08:00
|
|
|
Opts.RetainCommentsFromSystemHeaders =
|
|
|
|
Args.hasArg(OPT_fretain_comments_from_system_headers);
|
|
|
|
|
2013-06-15 01:17:23 +08:00
|
|
|
unsigned SSP = getLastArgIntValue(Args, OPT_stack_protector, 0, Diags);
|
2009-12-01 11:16:53 +08:00
|
|
|
switch (SSP) {
|
|
|
|
default:
|
|
|
|
Diags.Report(diag::err_drv_invalid_value)
|
|
|
|
<< Args.getLastArg(OPT_stack_protector)->getAsString(Args) << SSP;
|
|
|
|
break;
|
2011-09-14 01:21:33 +08:00
|
|
|
case 0: Opts.setStackProtector(LangOptions::SSPOff); break;
|
|
|
|
case 1: Opts.setStackProtector(LangOptions::SSPOn); break;
|
2014-02-11 09:35:14 +08:00
|
|
|
case 2: Opts.setStackProtector(LangOptions::SSPStrong); break;
|
|
|
|
case 3: Opts.setStackProtector(LangOptions::SSPReq); break;
|
2009-12-01 11:16:53 +08:00
|
|
|
}
|
2012-11-06 06:04:41 +08:00
|
|
|
|
Automatic variable initialization
Summary:
Add an option to initialize automatic variables with either a pattern or with
zeroes. The default is still that automatic variables are uninitialized. Also
add attributes to request uninitialized on a per-variable basis, mainly to disable
initialization of large stack arrays when deemed too expensive.
This isn't meant to change the semantics of C and C++. Rather, it's meant to be
a last-resort when programmers inadvertently have some undefined behavior in
their code. This patch aims to make undefined behavior hurt less, which
security-minded people will be very happy about. Notably, this means that
there's no inadvertent information leak when:
- The compiler re-uses stack slots, and a value is used uninitialized.
- The compiler re-uses a register, and a value is used uninitialized.
- Stack structs / arrays / unions with padding are copied.
This patch only addresses stack and register information leaks. There's many
more infoleaks that we could address, and much more undefined behavior that
could be tamed. Let's keep this patch focused, and I'm happy to address related
issues elsewhere.
To keep the patch simple, only some `undef` is removed for now, see
`replaceUndef`. The padding-related infoleaks are therefore not all gone yet.
This will be addressed in a follow-up, mainly because addressing padding-related
leaks should be a stand-alone option which is implied by variable
initialization.
There are three options when it comes to automatic variable initialization:
0. Uninitialized
This is C and C++'s default. It's not changing. Depending on code
generation, a programmer who runs into undefined behavior by using an
uninialized automatic variable may observe any previous value (including
program secrets), or any value which the compiler saw fit to materialize on
the stack or in a register (this could be to synthesize an immediate, to
refer to code or data locations, to generate cookies, etc).
1. Pattern initialization
This is the recommended initialization approach. Pattern initialization's
goal is to initialize automatic variables with values which will likely
transform logic bugs into crashes down the line, are easily recognizable in
a crash dump, without being values which programmers can rely on for useful
program semantics. At the same time, pattern initialization tries to
generate code which will optimize well. You'll find the following details in
`patternFor`:
- Integers are initialized with repeated 0xAA bytes (infinite scream).
- Vectors of integers are also initialized with infinite scream.
- Pointers are initialized with infinite scream on 64-bit platforms because
it's an unmappable pointer value on architectures I'm aware of. Pointers
are initialize to 0x000000AA (small scream) on 32-bit platforms because
32-bit platforms don't consistently offer unmappable pages. When they do
it's usually the zero page. As people try this out, I expect that we'll
want to allow different platforms to customize this, let's do so later.
- Vectors of pointers are initialized the same way pointers are.
- Floating point values and vectors are initialized with a negative quiet
NaN with repeated 0xFF payload (e.g. 0xffffffff and 0xffffffffffffffff).
NaNs are nice (here, anways) because they propagate on arithmetic, making
it more likely that entire computations become NaN when a single
uninitialized value sneaks in.
- Arrays are initialized to their homogeneous elements' initialization
value, repeated. Stack-based Variable-Length Arrays (VLAs) are
runtime-initialized to the allocated size (no effort is made for negative
size, but zero-sized VLAs are untouched even if technically undefined).
- Structs are initialized to their heterogeneous element's initialization
values. Zero-size structs are initialized as 0xAA since they're allocated
a single byte.
- Unions are initialized using the initialization for the largest member of
the union.
Expect the values used for pattern initialization to change over time, as we
refine heuristics (both for performance and security). The goal is truly to
avoid injecting semantics into undefined behavior, and we should be
comfortable changing these values when there's a worthwhile point in doing
so.
Why so much infinite scream? Repeated byte patterns tend to be easy to
synthesize on most architectures, and otherwise memset is usually very
efficient. For values which aren't entirely repeated byte patterns, LLVM
will often generate code which does memset + a few stores.
2. Zero initialization
Zero initialize all values. This has the unfortunate side-effect of
providing semantics to otherwise undefined behavior, programs therefore
might start to rely on this behavior, and that's sad. However, some
programmers believe that pattern initialization is too expensive for them,
and data might show that they're right. The only way to make these
programmers wrong is to offer zero-initialization as an option, figure out
where they are right, and optimize the compiler into submission. Until the
compiler provides acceptable performance for all security-minded code, zero
initialization is a useful (if blunt) tool.
I've been asked for a fourth initialization option: user-provided byte value.
This might be useful, and can easily be added later.
Why is an out-of band initialization mecanism desired? We could instead use
-Wuninitialized! Indeed we could, but then we're forcing the programmer to
provide semantics for something which doesn't actually have any (it's
uninitialized!). It's then unclear whether `int derp = 0;` lends meaning to `0`,
or whether it's just there to shut that warning up. It's also way easier to use
a compiler flag than it is to manually and intelligently initialize all values
in a program.
Why not just rely on static analysis? Because it cannot reason about all dynamic
code paths effectively, and it has false positives. It's a great tool, could get
even better, but it's simply incapable of catching all uses of uninitialized
values.
Why not just rely on memory sanitizer? Because it's not universally available,
has a 3x performance cost, and shouldn't be deployed in production. Again, it's
a great tool, it'll find the dynamic uses of uninitialized variables that your
test coverage hits, but it won't find the ones that you encounter in production.
What's the performance like? Not too bad! Previous publications [0] have cited
2.7 to 4.5% averages. We've commmitted a few patches over the last few months to
address specific regressions, both in code size and performance. In all cases,
the optimizations are generally useful, but variable initialization benefits
from them a lot more than regular code does. We've got a handful of other
optimizations in mind, but the code is in good enough shape and has found enough
latent issues that it's a good time to get the change reviewed, checked in, and
have others kick the tires. We'll continue reducing overheads as we try this out
on diverse codebases.
Is it a good idea? Security-minded folks think so, and apparently so does the
Microsoft Visual Studio team [1] who say "Between 2017 and mid 2018, this
feature would have killed 49 MSRC cases that involved uninitialized struct data
leaking across a trust boundary. It would have also mitigated a number of bugs
involving uninitialized struct data being used directly.". They seem to use pure
zero initialization, and claim to have taken the overheads down to within noise.
Don't just trust Microsoft though, here's another relevant person asking for
this [2]. It's been proposed for GCC [3] and LLVM [4] before.
What are the caveats? A few!
- Variables declared in unreachable code, and used later, aren't initialized.
This goto, Duff's device, other objectionable uses of switch. This should
instead be a hard-error in any serious codebase.
- Volatile stack variables are still weird. That's pre-existing, it's really
the language's fault and this patch keeps it weird. We should deprecate
volatile [5].
- As noted above, padding isn't fully handled yet.
I don't think these caveats make the patch untenable because they can be
addressed separately.
Should this be on by default? Maybe, in some circumstances. It's a conversation
we can have when we've tried it out sufficiently, and we're confident that we've
eliminated enough of the overheads that most codebases would want to opt-in.
Let's keep our precious undefined behavior until that point in time.
How do I use it:
1. On the command-line:
-ftrivial-auto-var-init=uninitialized (the default)
-ftrivial-auto-var-init=pattern
-ftrivial-auto-var-init=zero -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang
2. Using an attribute:
int dont_initialize_me __attribute((uninitialized));
[0]: https://users.elis.ugent.be/~jsartor/researchDocs/OOPSLA2011Zero-submit.pdf
[1]: https://twitter.com/JosephBialek/status/1062774315098112001
[2]: https://outflux.net/slides/2018/lss/danger.pdf
[3]: https://gcc.gnu.org/ml/gcc-patches/2014-06/msg00615.html
[4]: https://github.com/AndroidHardeningArchive/platform_external_clang/commit/776a0955ef6686d23a82d2e6a3cbd4a6a882c31c
[5]: http://wg21.link/p1152
I've also posted an RFC to cfe-dev: http://lists.llvm.org/pipermail/cfe-dev/2018-November/060172.html
<rdar://problem/39131435>
Reviewers: pcc, kcc, rsmith
Subscribers: JDevlieghere, jkorous, dexonsmith, cfe-commits
Differential Revision: https://reviews.llvm.org/D54604
llvm-svn: 349442
2018-12-18 13:12:21 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_ftrivial_auto_var_init)) {
|
|
|
|
StringRef Val = A->getValue();
|
|
|
|
if (Val == "uninitialized")
|
|
|
|
Opts.setTrivialAutoVarInit(
|
|
|
|
LangOptions::TrivialAutoVarInitKind::Uninitialized);
|
|
|
|
else if (Val == "zero")
|
|
|
|
Opts.setTrivialAutoVarInit(LangOptions::TrivialAutoVarInitKind::Zero);
|
|
|
|
else if (Val == "pattern")
|
|
|
|
Opts.setTrivialAutoVarInit(LangOptions::TrivialAutoVarInitKind::Pattern);
|
|
|
|
else
|
|
|
|
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
|
|
|
|
}
|
|
|
|
|
2012-11-06 06:04:41 +08:00
|
|
|
// Parse -fsanitize= arguments.
|
Reimplement -fsanitize-recover family of flags.
Introduce the following -fsanitize-recover flags:
- -fsanitize-recover=<list>: Enable recovery for selected checks or
group of checks. It is forbidden to explicitly list unrecoverable
sanitizers here (that is, "address", "unreachable", "return").
- -fno-sanitize-recover=<list>: Disable recovery for selected checks or
group of checks.
- -f(no-)?sanitize-recover is now a synonym for
-f(no-)?sanitize-recover=undefined,integer and will soon be deprecated.
These flags are parsed left to right, and mask of "recoverable"
sanitizer is updated accordingly, much like what we do for -fsanitize= flags.
-fsanitize= and -fsanitize-recover= flag families are independent.
CodeGen change: If there is a single UBSan handler function, responsible
for implementing multiple checks, which have different recoverable setting,
then we emit two handler calls instead of one:
the first one for the set of "unrecoverable" checks, another one - for
set of "recoverable" checks. If all checks implemented by a handler have the
same recoverability setting, then the generated code will be the same.
llvm-svn: 225719
2015-01-13 06:39:12 +08:00
|
|
|
parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ),
|
|
|
|
Diags, Opts.Sanitize);
|
2014-10-10 01:53:04 +08:00
|
|
|
// -fsanitize-address-field-padding=N has to be a LangOpt, parse it here.
|
2014-11-11 09:26:14 +08:00
|
|
|
Opts.SanitizeAddressFieldPadding =
|
2014-10-10 01:53:04 +08:00
|
|
|
getLastArgIntValue(Args, OPT_fsanitize_address_field_padding, 0, Diags);
|
2015-02-05 01:40:08 +08:00
|
|
|
Opts.SanitizerBlacklistFiles = Args.getAllArgValues(OPT_fsanitize_blacklist);
|
2017-03-30 08:29:36 +08:00
|
|
|
|
2017-03-31 06:46:45 +08:00
|
|
|
// -fxray-instrument
|
2017-03-30 08:29:36 +08:00
|
|
|
Opts.XRayInstrument =
|
|
|
|
Args.hasFlag(OPT_fxray_instrument, OPT_fnoxray_instrument, false);
|
2017-03-31 06:46:45 +08:00
|
|
|
|
2017-11-30 08:04:54 +08:00
|
|
|
// -fxray-always-emit-customevents
|
|
|
|
Opts.XRayAlwaysEmitCustomEvents =
|
|
|
|
Args.hasFlag(OPT_fxray_always_emit_customevents,
|
|
|
|
OPT_fnoxray_always_emit_customevents, false);
|
|
|
|
|
2018-04-18 05:32:43 +08:00
|
|
|
// -fxray-always-emit-typedevents
|
|
|
|
Opts.XRayAlwaysEmitTypedEvents =
|
|
|
|
Args.hasFlag(OPT_fxray_always_emit_typedevents,
|
|
|
|
OPT_fnoxray_always_emit_customevents, false);
|
|
|
|
|
2017-03-31 06:46:45 +08:00
|
|
|
// -fxray-{always,never}-instrument= filenames.
|
2017-03-30 08:29:36 +08:00
|
|
|
Opts.XRayAlwaysInstrumentFiles =
|
|
|
|
Args.getAllArgValues(OPT_fxray_always_instrument);
|
|
|
|
Opts.XRayNeverInstrumentFiles =
|
|
|
|
Args.getAllArgValues(OPT_fxray_never_instrument);
|
2018-04-09 12:02:09 +08:00
|
|
|
Opts.XRayAttrListFiles = Args.getAllArgValues(OPT_fxray_attr_list);
|
2017-04-19 16:58:56 +08:00
|
|
|
|
2018-06-13 21:55:42 +08:00
|
|
|
// -fforce-emit-vtables
|
|
|
|
Opts.ForceEmitVTables = Args.hasArg(OPT_fforce_emit_vtables);
|
|
|
|
|
2017-04-19 16:58:56 +08:00
|
|
|
// -fallow-editor-placeholders
|
|
|
|
Opts.AllowEditorPlaceholders = Args.hasArg(OPT_fallow_editor_placeholders);
|
2018-03-29 05:13:14 +08:00
|
|
|
|
2018-08-22 01:24:06 +08:00
|
|
|
Opts.RegisterStaticDestructors = !Args.hasArg(OPT_fno_cxx_static_destructors);
|
|
|
|
|
2018-03-29 05:13:14 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_fclang_abi_compat_EQ)) {
|
|
|
|
Opts.setClangABICompat(LangOptions::ClangABI::Latest);
|
|
|
|
|
|
|
|
StringRef Ver = A->getValue();
|
|
|
|
std::pair<StringRef, StringRef> VerParts = Ver.split('.');
|
|
|
|
unsigned Major, Minor = 0;
|
|
|
|
|
|
|
|
// Check the version number is valid: either 3.x (0 <= x <= 9) or
|
|
|
|
// y or y.0 (4 <= y <= current version).
|
|
|
|
if (!VerParts.first.startswith("0") &&
|
|
|
|
!VerParts.first.getAsInteger(10, Major) &&
|
|
|
|
3 <= Major && Major <= CLANG_VERSION_MAJOR &&
|
|
|
|
(Major == 3 ? VerParts.second.size() == 1 &&
|
|
|
|
!VerParts.second.getAsInteger(10, Minor)
|
|
|
|
: VerParts.first.size() == Ver.size() ||
|
|
|
|
VerParts.second == "0")) {
|
|
|
|
// Got a valid version number.
|
|
|
|
if (Major == 3 && Minor <= 8)
|
|
|
|
Opts.setClangABICompat(LangOptions::ClangABI::Ver3_8);
|
|
|
|
else if (Major <= 4)
|
|
|
|
Opts.setClangABICompat(LangOptions::ClangABI::Ver4);
|
2018-04-03 02:29:44 +08:00
|
|
|
else if (Major <= 6)
|
|
|
|
Opts.setClangABICompat(LangOptions::ClangABI::Ver6);
|
2018-10-27 03:26:45 +08:00
|
|
|
else if (Major <= 7)
|
|
|
|
Opts.setClangABICompat(LangOptions::ClangABI::Ver7);
|
2018-03-29 05:13:14 +08:00
|
|
|
} else if (Ver != "latest") {
|
|
|
|
Diags.Report(diag::err_drv_invalid_value)
|
|
|
|
<< A->getAsString(Args) << A->getValue();
|
|
|
|
}
|
|
|
|
}
|
2018-05-30 11:40:04 +08:00
|
|
|
|
|
|
|
Opts.CompleteMemberPointers = Args.hasArg(OPT_fcomplete_member_pointers);
|
2018-06-25 21:23:49 +08:00
|
|
|
Opts.BuildingPCHWithObjectFile = Args.hasArg(OPT_building_pch_with_obj);
|
2009-12-01 11:16:53 +08:00
|
|
|
}
|
|
|
|
|
2017-06-17 04:13:39 +08:00
|
|
|
static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {
|
|
|
|
switch (Action) {
|
|
|
|
case frontend::ASTDeclList:
|
|
|
|
case frontend::ASTDump:
|
|
|
|
case frontend::ASTPrint:
|
|
|
|
case frontend::ASTView:
|
|
|
|
case frontend::EmitAssembly:
|
|
|
|
case frontend::EmitBC:
|
|
|
|
case frontend::EmitHTML:
|
|
|
|
case frontend::EmitLLVM:
|
|
|
|
case frontend::EmitLLVMOnly:
|
|
|
|
case frontend::EmitCodeGenOnly:
|
|
|
|
case frontend::EmitObj:
|
|
|
|
case frontend::FixIt:
|
|
|
|
case frontend::GenerateModule:
|
|
|
|
case frontend::GenerateModuleInterface:
|
2018-09-15 09:21:15 +08:00
|
|
|
case frontend::GenerateHeaderModule:
|
2017-06-17 04:13:39 +08:00
|
|
|
case frontend::GeneratePCH:
|
2019-08-23 07:29:22 +08:00
|
|
|
case frontend::GenerateInterfaceIfsExpV1:
|
2017-06-17 04:13:39 +08:00
|
|
|
case frontend::ParseSyntaxOnly:
|
|
|
|
case frontend::ModuleFileInfo:
|
|
|
|
case frontend::VerifyPCH:
|
|
|
|
case frontend::PluginAction:
|
|
|
|
case frontend::RewriteObjC:
|
|
|
|
case frontend::RewriteTest:
|
|
|
|
case frontend::RunAnalysis:
|
2018-02-10 22:04:45 +08:00
|
|
|
case frontend::TemplightDump:
|
2017-06-17 04:13:39 +08:00
|
|
|
case frontend::MigrateSource:
|
|
|
|
return false;
|
|
|
|
|
2018-05-31 21:57:09 +08:00
|
|
|
case frontend::DumpCompilerOptions:
|
2017-06-17 04:13:39 +08:00
|
|
|
case frontend::DumpRawTokens:
|
|
|
|
case frontend::DumpTokens:
|
|
|
|
case frontend::InitOnly:
|
|
|
|
case frontend::PrintPreamble:
|
|
|
|
case frontend::PrintPreprocessedInput:
|
|
|
|
case frontend::RewriteMacros:
|
|
|
|
case frontend::RunPreprocessorOnly:
|
2019-06-04 06:59:17 +08:00
|
|
|
case frontend::PrintDependencyDirectivesSourceMinimizerOutput:
|
2017-06-17 04:13:39 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
llvm_unreachable("invalid frontend action");
|
|
|
|
}
|
|
|
|
|
2009-12-03 13:11:16 +08:00
|
|
|
static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
|
2017-06-17 04:13:39 +08:00
|
|
|
DiagnosticsEngine &Diags,
|
|
|
|
frontend::ActionKind Action) {
|
2010-05-21 00:54:55 +08:00
|
|
|
Opts.ImplicitPCHInclude = Args.getLastArgValue(OPT_include_pch);
|
2018-09-12 01:10:44 +08:00
|
|
|
Opts.PCHWithHdrStop = Args.hasArg(OPT_pch_through_hdrstop_create) ||
|
|
|
|
Args.hasArg(OPT_pch_through_hdrstop_use);
|
|
|
|
Opts.PCHWithHdrStopCreate = Args.hasArg(OPT_pch_through_hdrstop_create);
|
2018-07-06 01:22:13 +08:00
|
|
|
Opts.PCHThroughHeader = Args.getLastArgValue(OPT_pch_through_header_EQ);
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.UsePredefines = !Args.hasArg(OPT_undef);
|
2010-03-20 00:15:56 +08:00
|
|
|
Opts.DetailedRecord = Args.hasArg(OPT_detailed_preprocessing_record);
|
2010-07-27 08:27:13 +08:00
|
|
|
Opts.DisablePCHValidation = Args.hasArg(OPT_fno_validate_pch);
|
2017-02-27 10:06:18 +08:00
|
|
|
Opts.AllowPCHWithCompilerErrors = Args.hasArg(OPT_fallow_pch_with_errors);
|
2010-10-15 04:14:25 +08:00
|
|
|
|
2010-10-15 04:14:18 +08:00
|
|
|
Opts.DumpDeserializedPCHDecls = Args.hasArg(OPT_dump_deserialized_pch_decls);
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *A : Args.filtered(OPT_error_on_deserialized_pch_decl))
|
2012-11-01 12:30:05 +08:00
|
|
|
Opts.DeserializedPCHDeclsToErrorOn.insert(A->getValue());
|
2010-07-27 08:27:13 +08:00
|
|
|
|
Introduce basic support for loading a precompiled preamble while
reparsing an ASTUnit. When saving a preamble, create a buffer larger
than the actual file we're working with but fill everything from the
end of the preamble to the end of the file with spaces (so the lexer
will quickly skip them). When we load the file, create a buffer of the
same size, filling it with the file and then spaces. Then, instruct
the lexer to start lexing after the preamble, therefore continuing the
parse from the spot where the preamble left off.
It's now possible to perform a simple preamble build + parse (+
reparse) with ASTUnit. However, one has to disable a bunch of checking
in the PCH reader to do so. That part isn't committed; it will likely
be handled with some other kind of flag (e.g., -fno-validate-pch).
As part of this, fix some issues with null termination of the memory
buffers created for the preamble; we were trying to explicitly
NULL-terminate them, even though they were also getting implicitly
NULL terminated, leading to excess warnings about NULL characters in
source files.
llvm-svn: 109445
2010-07-27 05:36:20 +08:00
|
|
|
if (const Arg *A = Args.getLastArg(OPT_preamble_bytes_EQ)) {
|
2012-11-01 12:30:05 +08:00
|
|
|
StringRef Value(A->getValue());
|
Introduce basic support for loading a precompiled preamble while
reparsing an ASTUnit. When saving a preamble, create a buffer larger
than the actual file we're working with but fill everything from the
end of the preamble to the end of the file with spaces (so the lexer
will quickly skip them). When we load the file, create a buffer of the
same size, filling it with the file and then spaces. Then, instruct
the lexer to start lexing after the preamble, therefore continuing the
parse from the spot where the preamble left off.
It's now possible to perform a simple preamble build + parse (+
reparse) with ASTUnit. However, one has to disable a bunch of checking
in the PCH reader to do so. That part isn't committed; it will likely
be handled with some other kind of flag (e.g., -fno-validate-pch).
As part of this, fix some issues with null termination of the memory
buffers created for the preamble; we were trying to explicitly
NULL-terminate them, even though they were also getting implicitly
NULL terminated, leading to excess warnings about NULL characters in
source files.
llvm-svn: 109445
2010-07-27 05:36:20 +08:00
|
|
|
size_t Comma = Value.find(',');
|
|
|
|
unsigned Bytes = 0;
|
|
|
|
unsigned EndOfLine = 0;
|
2010-10-21 11:16:25 +08:00
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
if (Comma == StringRef::npos ||
|
Introduce basic support for loading a precompiled preamble while
reparsing an ASTUnit. When saving a preamble, create a buffer larger
than the actual file we're working with but fill everything from the
end of the preamble to the end of the file with spaces (so the lexer
will quickly skip them). When we load the file, create a buffer of the
same size, filling it with the file and then spaces. Then, instruct
the lexer to start lexing after the preamble, therefore continuing the
parse from the spot where the preamble left off.
It's now possible to perform a simple preamble build + parse (+
reparse) with ASTUnit. However, one has to disable a bunch of checking
in the PCH reader to do so. That part isn't committed; it will likely
be handled with some other kind of flag (e.g., -fno-validate-pch).
As part of this, fix some issues with null termination of the memory
buffers created for the preamble; we were trying to explicitly
NULL-terminate them, even though they were also getting implicitly
NULL terminated, leading to excess warnings about NULL characters in
source files.
llvm-svn: 109445
2010-07-27 05:36:20 +08:00
|
|
|
Value.substr(0, Comma).getAsInteger(10, Bytes) ||
|
|
|
|
Value.substr(Comma + 1).getAsInteger(10, EndOfLine))
|
|
|
|
Diags.Report(diag::err_drv_preamble_format);
|
|
|
|
else {
|
|
|
|
Opts.PrecompiledPreambleBytes.first = Bytes;
|
|
|
|
Opts.PrecompiledPreambleBytes.second = (EndOfLine != 0);
|
|
|
|
}
|
|
|
|
}
|
2010-10-21 11:16:25 +08:00
|
|
|
|
2018-05-18 19:56:21 +08:00
|
|
|
// Add the __CET__ macro if a CFProtection option is set.
|
|
|
|
if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) {
|
|
|
|
StringRef Name = A->getValue();
|
|
|
|
if (Name == "branch")
|
|
|
|
Opts.addMacroDef("__CET__=1");
|
|
|
|
else if (Name == "return")
|
|
|
|
Opts.addMacroDef("__CET__=2");
|
|
|
|
else if (Name == "full")
|
|
|
|
Opts.addMacroDef("__CET__=3");
|
|
|
|
}
|
|
|
|
|
2009-12-01 11:16:53 +08:00
|
|
|
// Add macros from the command line.
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *A : Args.filtered(OPT_D, OPT_U)) {
|
2015-06-09 09:57:17 +08:00
|
|
|
if (A->getOption().matches(OPT_D))
|
|
|
|
Opts.addMacroDef(A->getValue());
|
2009-12-01 11:16:53 +08:00
|
|
|
else
|
2015-06-09 09:57:17 +08:00
|
|
|
Opts.addMacroUndef(A->getValue());
|
2009-12-01 11:16:53 +08:00
|
|
|
}
|
|
|
|
|
2010-05-21 00:54:55 +08:00
|
|
|
Opts.MacroIncludes = Args.getAllArgValues(OPT_imacros);
|
2009-12-01 11:16:53 +08:00
|
|
|
|
|
|
|
// Add the ordered list of -includes.
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *A : Args.filtered(OPT_include))
|
2015-05-30 03:42:19 +08:00
|
|
|
Opts.Includes.emplace_back(A->getValue());
|
2009-12-03 13:11:16 +08:00
|
|
|
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *A : Args.filtered(OPT_chain_include))
|
2015-05-30 03:42:19 +08:00
|
|
|
Opts.ChainedIncludes.emplace_back(A->getValue());
|
2011-03-10 01:21:42 +08:00
|
|
|
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *A : Args.filtered(OPT_remap_file)) {
|
2015-06-09 09:57:17 +08:00
|
|
|
std::pair<StringRef, StringRef> Split = StringRef(A->getValue()).split(';');
|
2009-12-03 13:11:16 +08:00
|
|
|
|
|
|
|
if (Split.second.empty()) {
|
2010-06-12 06:00:13 +08:00
|
|
|
Diags.Report(diag::err_drv_invalid_remap_file) << A->getAsString(Args);
|
2009-12-03 13:11:16 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
Opts.addRemappedFile(Split.first, Split.second);
|
|
|
|
}
|
2015-06-09 09:57:17 +08:00
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_fobjc_arc_cxxlib_EQ)) {
|
2012-11-01 12:30:05 +08:00
|
|
|
StringRef Name = A->getValue();
|
2011-06-16 07:02:42 +08:00
|
|
|
unsigned Library = llvm::StringSwitch<unsigned>(Name)
|
|
|
|
.Case("libc++", ARCXX_libcxx)
|
|
|
|
.Case("libstdc++", ARCXX_libstdcxx)
|
|
|
|
.Case("none", ARCXX_nolib)
|
|
|
|
.Default(~0U);
|
|
|
|
if (Library == ~0U)
|
|
|
|
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
|
|
|
|
else
|
|
|
|
Opts.ObjCXXARCStandardLibrary = (ObjCXXARCStandardLibraryKind)Library;
|
|
|
|
}
|
2017-06-17 04:13:39 +08:00
|
|
|
|
|
|
|
// Always avoid lexing editor placeholders when we're just running the
|
|
|
|
// preprocessor as we never want to emit the
|
|
|
|
// "editor placeholder in source file" error in PP only mode.
|
|
|
|
if (isStrictlyPreprocessorAction(Action))
|
|
|
|
Opts.LexEditorPlaceholders = false;
|
2009-12-01 11:16:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
|
2013-01-30 09:52:57 +08:00
|
|
|
ArgList &Args,
|
|
|
|
frontend::ActionKind Action) {
|
2017-06-17 04:13:39 +08:00
|
|
|
if (isStrictlyPreprocessorAction(Action))
|
2013-01-30 09:52:57 +08:00
|
|
|
Opts.ShowCPP = !Args.hasArg(OPT_dM);
|
2017-06-17 04:13:39 +08:00
|
|
|
else
|
|
|
|
Opts.ShowCPP = 0;
|
2013-01-30 09:52:57 +08:00
|
|
|
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.ShowComments = Args.hasArg(OPT_C);
|
2010-08-25 06:44:13 +08:00
|
|
|
Opts.ShowLineMarkers = !Args.hasArg(OPT_P);
|
2009-12-01 11:16:53 +08:00
|
|
|
Opts.ShowMacroComments = Args.hasArg(OPT_CC);
|
2010-08-25 06:44:13 +08:00
|
|
|
Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD);
|
2016-11-18 06:45:31 +08:00
|
|
|
Opts.ShowIncludeDirectives = Args.hasArg(OPT_dI);
|
2012-06-15 01:36:09 +08:00
|
|
|
Opts.RewriteIncludes = Args.hasArg(OPT_frewrite_includes);
|
2017-06-10 05:24:02 +08:00
|
|
|
Opts.RewriteImports = Args.hasArg(OPT_frewrite_imports);
|
2015-02-26 08:17:25 +08:00
|
|
|
Opts.UseLineDirectives = Args.hasArg(OPT_fuse_line_directives);
|
2009-12-01 11:16:53 +08:00
|
|
|
}
|
|
|
|
|
2016-04-09 00:52:05 +08:00
|
|
|
static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args,
|
|
|
|
DiagnosticsEngine &Diags) {
|
2018-10-09 06:25:20 +08:00
|
|
|
Opts.CodeModel = getCodeModel(Args, Diags);
|
2010-05-21 00:54:55 +08:00
|
|
|
Opts.ABI = Args.getLastArgValue(OPT_target_abi);
|
2016-04-09 00:52:05 +08:00
|
|
|
if (Arg *A = Args.getLastArg(OPT_meabi)) {
|
|
|
|
StringRef Value = A->getValue();
|
|
|
|
llvm::EABI EABIVersion = llvm::StringSwitch<llvm::EABI>(Value)
|
|
|
|
.Case("default", llvm::EABI::Default)
|
|
|
|
.Case("4", llvm::EABI::EABI4)
|
|
|
|
.Case("5", llvm::EABI::EABI5)
|
|
|
|
.Case("gnu", llvm::EABI::GNU)
|
|
|
|
.Default(llvm::EABI::Unknown);
|
|
|
|
if (EABIVersion == llvm::EABI::Unknown)
|
|
|
|
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
|
|
|
|
<< Value;
|
|
|
|
else
|
2017-07-01 15:57:23 +08:00
|
|
|
Opts.EABIVersion = EABIVersion;
|
2016-04-09 00:52:05 +08:00
|
|
|
}
|
2010-05-21 00:54:55 +08:00
|
|
|
Opts.CPU = Args.getLastArgValue(OPT_target_cpu);
|
2013-08-22 05:59:03 +08:00
|
|
|
Opts.FPMath = Args.getLastArgValue(OPT_mfpmath);
|
2012-10-17 07:40:58 +08:00
|
|
|
Opts.FeaturesAsWritten = Args.getAllArgValues(OPT_target_feature);
|
2010-08-12 07:07:42 +08:00
|
|
|
Opts.LinkerVersion = Args.getLastArgValue(OPT_target_linker_version);
|
2018-05-26 04:39:37 +08:00
|
|
|
Opts.Triple = Args.getLastArgValue(OPT_triple);
|
2011-11-02 05:33:06 +08:00
|
|
|
// Use the default target triple if unspecified.
|
2009-12-01 11:16:53 +08:00
|
|
|
if (Opts.Triple.empty())
|
2011-11-02 05:33:06 +08:00
|
|
|
Opts.Triple = llvm::sys::getDefaultTargetTriple();
|
2018-05-26 04:39:37 +08:00
|
|
|
Opts.Triple = llvm::Triple::normalize(Opts.Triple);
|
2016-11-01 23:50:52 +08:00
|
|
|
Opts.OpenCLExtensionsAsWritten = Args.getAllArgValues(OPT_cl_ext_EQ);
|
[RISCV] Enable __int128_t and __uint128_t through clang flag
Summary:
If the flag -fforce-enable-int128 is passed, it will enable support for __int128_t and __uint128_t types.
This flag can then be used to build compiler-rt for RISCV32.
Reviewers: asb, kito-cheng, apazos, efriedma
Reviewed By: asb, efriedma
Subscribers: shiva0217, efriedma, jfb, dschuff, sdardis, sbc100, jgravelle-google, aheejin, rbar, johnrusso, simoncook, jordy.potman.lists, sabuasal, niosHD, cfe-commits
Differential Revision: https://reviews.llvm.org/D43105
llvm-svn: 326045
2018-02-25 11:58:23 +08:00
|
|
|
Opts.ForceEnableInt128 = Args.hasArg(OPT_fforce_enable_int128);
|
2018-05-10 07:10:09 +08:00
|
|
|
Opts.NVPTXUseShortPointers = Args.hasFlag(
|
|
|
|
options::OPT_fcuda_short_ptr, options::OPT_fno_cuda_short_ptr, false);
|
2018-12-18 03:19:15 +08:00
|
|
|
if (Arg *A = Args.getLastArg(options::OPT_target_sdk_version_EQ)) {
|
|
|
|
llvm::VersionTuple Version;
|
|
|
|
if (Version.tryParse(A->getValue()))
|
|
|
|
Diags.Report(diag::err_drv_invalid_value)
|
|
|
|
<< A->getAsString(Args) << A->getValue();
|
|
|
|
else
|
|
|
|
Opts.SDKVersion = Version;
|
|
|
|
}
|
2014-01-14 03:48:18 +08:00
|
|
|
}
|
2009-12-01 11:16:53 +08:00
|
|
|
|
2011-12-23 11:05:38 +08:00
|
|
|
bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
|
2019-08-28 06:13:31 +08:00
|
|
|
ArrayRef<const char *> CommandLineArgs,
|
2011-09-26 07:23:43 +08:00
|
|
|
DiagnosticsEngine &Diags) {
|
2011-12-23 11:05:38 +08:00
|
|
|
bool Success = true;
|
|
|
|
|
2009-12-01 11:16:53 +08:00
|
|
|
// Parse the arguments.
|
2017-01-14 01:34:15 +08:00
|
|
|
std::unique_ptr<OptTable> Opts = createDriverOptTable();
|
2013-08-03 04:16:22 +08:00
|
|
|
const unsigned IncludedFlagsBitmask = options::CC1Option;
|
2009-12-01 11:16:53 +08:00
|
|
|
unsigned MissingArgIndex, MissingArgCount;
|
2019-08-28 06:13:31 +08:00
|
|
|
InputArgList Args = Opts->ParseArgs(CommandLineArgs, MissingArgIndex,
|
|
|
|
MissingArgCount, IncludedFlagsBitmask);
|
2016-04-09 01:42:32 +08:00
|
|
|
LangOptions &LangOpts = *Res.getLangOpts();
|
2009-12-01 11:16:53 +08:00
|
|
|
|
|
|
|
// Check for missing argument error.
|
2011-12-23 11:05:38 +08:00
|
|
|
if (MissingArgCount) {
|
2009-12-01 11:16:53 +08:00
|
|
|
Diags.Report(diag::err_drv_missing_argument)
|
2015-06-23 06:07:27 +08:00
|
|
|
<< Args.getArgString(MissingArgIndex) << MissingArgCount;
|
2011-12-23 11:05:38 +08:00
|
|
|
Success = false;
|
|
|
|
}
|
2009-12-01 11:16:53 +08:00
|
|
|
|
|
|
|
// Issue errors on unknown arguments.
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto *A : Args.filtered(OPT_UNKNOWN)) {
|
[Driver] Suggest correctly spelled driver options
Summary:
Depends on https://reviews.llvm.org/D41732.
Utilities such as `opt`, when invoked with arguments that are very
nearly spelled correctly, suggest the correctly spelled options:
```
bin/opt -hel
opt: Unknown command line argument '-hel'. Try: 'bin/opt -help'
opt: Did you mean '-help'?
```
Clang, on the other hand, prior to this commit, does not:
```
bin/clang -hel
clang-6.0: error: unknown argument: '-hel'
```
This commit makes use of the new libLLVMOption API from
https://reviews.llvm.org/D41732 in order to provide correct suggestions:
```
bin/clang -hel
clang-6.0: error: unknown argument: '-hel', did you mean '-help'?
```
Test Plan: `check-clang`
Reviewers: yamaguchi, v.g.vassilev, teemperor, ruiu, bruno
Reviewed By: bruno
Subscribers: bruno, jroelofs, cfe-commits
Differential Revision: https://reviews.llvm.org/D41733
llvm-svn: 321917
2018-01-06 08:25:40 +08:00
|
|
|
auto ArgString = A->getAsString(Args);
|
|
|
|
std::string Nearest;
|
|
|
|
if (Opts->findNearest(ArgString, Nearest, IncludedFlagsBitmask) > 1)
|
|
|
|
Diags.Report(diag::err_drv_unknown_argument) << ArgString;
|
|
|
|
else
|
|
|
|
Diags.Report(diag::err_drv_unknown_argument_with_suggestion)
|
|
|
|
<< ArgString << Nearest;
|
2011-12-23 11:05:38 +08:00
|
|
|
Success = false;
|
|
|
|
}
|
2009-12-01 11:16:53 +08:00
|
|
|
|
2015-06-23 06:07:27 +08:00
|
|
|
Success &= ParseAnalyzerArgs(*Res.getAnalyzerOpts(), Args, Diags);
|
|
|
|
Success &= ParseMigratorArgs(Res.getMigratorOpts(), Args);
|
|
|
|
ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), Args);
|
2016-10-12 02:21:26 +08:00
|
|
|
Success &=
|
|
|
|
ParseDiagnosticArgs(Res.getDiagnosticOpts(), Args, &Diags,
|
|
|
|
false /*DefaultDiagColor*/, false /*DefaultShowOpt*/);
|
2016-04-09 01:42:32 +08:00
|
|
|
ParseCommentArgs(LangOpts.CommentOpts, Args);
|
2015-06-23 06:07:27 +08:00
|
|
|
ParseFileSystemArgs(Res.getFileSystemOpts(), Args);
|
2010-12-04 09:50:36 +08:00
|
|
|
// FIXME: We shouldn't have to pass the DashX option around here
|
2016-10-27 22:17:10 +08:00
|
|
|
InputKind DashX = ParseFrontendArgs(Res.getFrontendOpts(), Args, Diags,
|
|
|
|
LangOpts.IsHeaderFile);
|
2016-04-09 00:52:05 +08:00
|
|
|
ParseTargetArgs(Res.getTargetOpts(), Args, Diags);
|
2015-06-23 06:07:27 +08:00
|
|
|
Success &= ParseCodeGenArgs(Res.getCodeGenOpts(), Args, DashX, Diags,
|
2018-04-18 00:39:25 +08:00
|
|
|
Res.getTargetOpts(), Res.getFrontendOpts());
|
2017-03-15 07:07:49 +08:00
|
|
|
ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args,
|
|
|
|
Res.getFileSystemOpts().WorkingDir);
|
2018-12-07 06:45:58 +08:00
|
|
|
llvm::Triple T(Res.getTargetOpts().Triple);
|
2017-04-27 02:57:40 +08:00
|
|
|
if (DashX.getFormat() == InputKind::Precompiled ||
|
2019-08-05 21:59:26 +08:00
|
|
|
DashX.getLanguage() == Language::LLVM_IR) {
|
2015-07-18 04:09:56 +08:00
|
|
|
// ObjCAAutoRefCount and Sanitize LangOpts are used to setup the
|
|
|
|
// PassManager in BackendUtil.cpp. They need to be initializd no matter
|
|
|
|
// what the input type is.
|
|
|
|
if (Args.hasArg(OPT_fobjc_arc))
|
2016-04-09 01:42:32 +08:00
|
|
|
LangOpts.ObjCAutoRefCount = 1;
|
|
|
|
// PIClevel and PIELevel are needed during code generation and this should be
|
|
|
|
// set regardless of the input type.
|
|
|
|
LangOpts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags);
|
2016-06-23 23:07:32 +08:00
|
|
|
LangOpts.PIE = Args.hasArg(OPT_pic_is_pie);
|
2015-07-18 04:09:56 +08:00
|
|
|
parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ),
|
2016-04-09 01:42:32 +08:00
|
|
|
Diags, LangOpts.Sanitize);
|
2015-07-18 04:09:56 +08:00
|
|
|
} else {
|
Misc typos fixes in ./lib folder
Summary: Found via `codespell -q 3 -I ../clang-whitelist.txt -L uint,importd,crasher,gonna,cant,ue,ons,orign,ned`
Reviewers: teemperor
Reviewed By: teemperor
Subscribers: teemperor, jholewinski, jvesely, nhaehnle, whisperity, jfb, cfe-commits
Differential Revision: https://reviews.llvm.org/D55475
llvm-svn: 348755
2018-12-10 20:37:46 +08:00
|
|
|
// Other LangOpts are only initialized when the input is not AST or LLVM IR.
|
2019-08-05 21:59:26 +08:00
|
|
|
// FIXME: Should we really be calling this for an Language::Asm input?
|
2016-06-21 03:26:00 +08:00
|
|
|
ParseLangArgs(LangOpts, Args, DashX, Res.getTargetOpts(),
|
2017-04-27 02:57:40 +08:00
|
|
|
Res.getPreprocessorOpts(), Diags);
|
2011-02-26 01:24:55 +08:00
|
|
|
if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC)
|
2016-04-09 01:42:32 +08:00
|
|
|
LangOpts.ObjCExceptions = 1;
|
2018-12-07 06:45:58 +08:00
|
|
|
if (T.isOSDarwin() && DashX.isPreprocessed()) {
|
|
|
|
// Supress the darwin-specific 'stdlibcxx-not-found' diagnostic for
|
|
|
|
// preprocessed input as we don't expect it to be used with -std=libc++
|
|
|
|
// anyway.
|
|
|
|
Res.getDiagnosticOpts().Warnings.push_back("no-stdlibcxx-not-found");
|
|
|
|
}
|
2011-02-26 01:24:55 +08:00
|
|
|
}
|
2016-03-14 21:23:58 +08:00
|
|
|
|
2018-04-20 07:14:57 +08:00
|
|
|
LangOpts.FunctionAlignment =
|
|
|
|
getLastArgIntValue(Args, OPT_function_alignment, 0, Diags);
|
|
|
|
|
2016-05-20 02:44:45 +08:00
|
|
|
if (LangOpts.CUDA) {
|
|
|
|
// During CUDA device-side compilation, the aux triple is the
|
|
|
|
// triple used for host compilation.
|
|
|
|
if (LangOpts.CUDAIsDevice)
|
|
|
|
Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple;
|
2016-04-30 07:05:19 +08:00
|
|
|
}
|
|
|
|
|
[OpenMP] Add support for auxiliary triple specification
Summary: Device offloading requires the specification of an additional flag containing the triple of the //other// architecture the code is being compiled on if such an architecture exists. If compiling for the host, the auxiliary triple flag will contain the triple describing the device and vice versa.
Reviewers: arpith-jacob, sfantao, caomhin, carlo.bertolli, ABataev, Hahnfeld, jlebar, hfinkel, tstellar
Reviewed By: Hahnfeld
Subscribers: rengolin, cfe-commits
Differential Revision: https://reviews.llvm.org/D29339
llvm-svn: 306689
2017-06-29 23:49:03 +08:00
|
|
|
// Set the triple of the host for OpenMP device compile.
|
|
|
|
if (LangOpts.OpenMPIsDevice)
|
|
|
|
Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple;
|
|
|
|
|
2016-03-15 17:41:39 +08:00
|
|
|
// FIXME: Override value name discarding when asan or msan is used because the
|
2016-03-14 21:23:58 +08:00
|
|
|
// backend passes depend on the name of the alloca in order to print out
|
|
|
|
// names.
|
2016-03-15 17:41:39 +08:00
|
|
|
Res.getCodeGenOpts().DiscardValueNames &=
|
2016-04-09 01:42:32 +08:00
|
|
|
!LangOpts.Sanitize.has(SanitizerKind::Address) &&
|
2018-09-07 17:21:09 +08:00
|
|
|
!LangOpts.Sanitize.has(SanitizerKind::KernelAddress) &&
|
|
|
|
!LangOpts.Sanitize.has(SanitizerKind::Memory) &&
|
|
|
|
!LangOpts.Sanitize.has(SanitizerKind::KernelMemory);
|
2016-03-14 21:23:58 +08:00
|
|
|
|
2018-01-10 05:26:47 +08:00
|
|
|
ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, Diags,
|
2017-06-17 04:13:39 +08:00
|
|
|
Res.getFrontendOpts().ProgramAction);
|
2015-06-23 06:07:27 +08:00
|
|
|
ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), Args,
|
2013-01-30 09:52:57 +08:00
|
|
|
Res.getFrontendOpts().ProgramAction);
|
2016-07-29 03:26:30 +08:00
|
|
|
|
|
|
|
// Turn on -Wspir-compat for SPIR target.
|
2019-05-09 18:25:45 +08:00
|
|
|
if (T.isSPIR())
|
2016-07-29 03:26:30 +08:00
|
|
|
Res.getDiagnosticOpts().Warnings.push_back("spir-compat");
|
2017-10-17 00:50:27 +08:00
|
|
|
|
|
|
|
// If sanitizer is enabled, disable OPT_ffine_grained_bitfield_accesses.
|
|
|
|
if (Res.getCodeGenOpts().FineGrainedBitfieldAccesses &&
|
|
|
|
!Res.getLangOpts()->Sanitize.empty()) {
|
|
|
|
Res.getCodeGenOpts().FineGrainedBitfieldAccesses = false;
|
|
|
|
Diags.Report(diag::warn_drv_fine_grained_bitfield_accesses_ignored);
|
|
|
|
}
|
2011-12-23 11:05:38 +08:00
|
|
|
return Success;
|
2009-12-01 11:16:53 +08:00
|
|
|
}
|
2011-09-14 07:15:45 +08:00
|
|
|
|
|
|
|
std::string CompilerInvocation::getModuleHash() const {
|
2013-03-28 00:47:18 +08:00
|
|
|
// Note: For QoI reasons, the things we use as a hash here should all be
|
|
|
|
// dumped via the -module-info flag.
|
2012-11-06 03:45:09 +08:00
|
|
|
using llvm::hash_code;
|
|
|
|
using llvm::hash_value;
|
|
|
|
using llvm::hash_combine;
|
|
|
|
|
2011-09-14 07:15:45 +08:00
|
|
|
// Start the signature with the compiler version.
|
2012-11-06 07:30:26 +08:00
|
|
|
// FIXME: We'd rather use something more cryptographically sound than
|
2012-11-06 03:45:09 +08:00
|
|
|
// CityHash, but this will do for now.
|
|
|
|
hash_code code = hash_value(getClangFullRepositoryVersion());
|
|
|
|
|
2011-09-14 07:15:45 +08:00
|
|
|
// Extend the signature with the language options
|
|
|
|
#define LANGOPT(Name, Bits, Default, Description) \
|
2012-11-06 03:45:09 +08:00
|
|
|
code = hash_combine(code, LangOpts->Name);
|
2011-09-14 07:15:45 +08:00
|
|
|
#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
|
2012-11-06 03:45:09 +08:00
|
|
|
code = hash_combine(code, static_cast<unsigned>(LangOpts->get##Name()));
|
2011-09-14 07:15:45 +08:00
|
|
|
#define BENIGN_LANGOPT(Name, Bits, Default, Description)
|
|
|
|
#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)
|
|
|
|
#include "clang/Basic/LangOptions.def"
|
2015-06-24 02:20:18 +08:00
|
|
|
|
|
|
|
for (StringRef Feature : LangOpts->ModuleFeatures)
|
|
|
|
code = hash_combine(code, Feature);
|
2015-08-05 23:08:53 +08:00
|
|
|
|
2012-11-06 03:45:09 +08:00
|
|
|
// Extend the signature with the target options.
|
|
|
|
code = hash_combine(code, TargetOpts->Triple, TargetOpts->CPU,
|
2014-04-30 02:45:01 +08:00
|
|
|
TargetOpts->ABI);
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto &FeatureAsWritten : TargetOpts->FeaturesAsWritten)
|
|
|
|
code = hash_combine(code, FeatureAsWritten);
|
2011-09-14 07:15:45 +08:00
|
|
|
|
2011-09-14 23:55:12 +08:00
|
|
|
// Extend the signature with preprocessor options.
|
2012-11-06 03:45:09 +08:00
|
|
|
const PreprocessorOptions &ppOpts = getPreprocessorOpts();
|
2013-02-07 08:21:12 +08:00
|
|
|
const HeaderSearchOptions &hsOpts = getHeaderSearchOpts();
|
2012-11-06 03:45:09 +08:00
|
|
|
code = hash_combine(code, ppOpts.UsePredefines, ppOpts.DetailedRecord);
|
|
|
|
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto &I : getPreprocessorOpts().Macros) {
|
2013-02-07 08:21:12 +08:00
|
|
|
// If we're supposed to ignore this macro for the purposes of modules,
|
|
|
|
// don't put it into the hash.
|
|
|
|
if (!hsOpts.ModulesIgnoreMacros.empty()) {
|
|
|
|
// Check whether we're ignoring this macro.
|
2018-03-27 05:45:04 +08:00
|
|
|
StringRef MacroDef = I.first;
|
2016-10-22 05:45:01 +08:00
|
|
|
if (hsOpts.ModulesIgnoreMacros.count(
|
|
|
|
llvm::CachedHashString(MacroDef.split('=').first)))
|
2013-02-07 08:21:12 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-03-27 05:45:04 +08:00
|
|
|
code = hash_combine(code, I.first, I.second);
|
2011-10-17 22:55:37 +08:00
|
|
|
}
|
2012-11-06 03:45:09 +08:00
|
|
|
|
2016-01-13 05:01:56 +08:00
|
|
|
// Extend the signature with the sysroot and other header search options.
|
|
|
|
code = hash_combine(code, hsOpts.Sysroot,
|
|
|
|
hsOpts.ModuleFormat,
|
|
|
|
hsOpts.UseDebugInfo,
|
|
|
|
hsOpts.UseBuiltinIncludes,
|
2012-11-06 03:45:09 +08:00
|
|
|
hsOpts.UseStandardSystemIncludes,
|
|
|
|
hsOpts.UseStandardCXXIncludes,
|
2016-07-27 01:12:17 +08:00
|
|
|
hsOpts.UseLibcxx,
|
|
|
|
hsOpts.ModulesValidateDiagnosticOptions);
|
2014-05-04 13:27:24 +08:00
|
|
|
code = hash_combine(code, hsOpts.ResourceDir);
|
2012-11-06 03:45:09 +08:00
|
|
|
|
2014-03-03 16:12:05 +08:00
|
|
|
// Extend the signature with the user build path.
|
|
|
|
code = hash_combine(code, hsOpts.ModuleUserBuildPath);
|
|
|
|
|
2015-11-04 02:33:07 +08:00
|
|
|
// Extend the signature with the module file extensions.
|
|
|
|
const FrontendOptions &frontendOpts = getFrontendOpts();
|
2016-05-27 21:36:58 +08:00
|
|
|
for (const auto &ext : frontendOpts.ModuleFileExtensions) {
|
2015-11-04 02:33:07 +08:00
|
|
|
code = ext->hashExtension(code);
|
|
|
|
}
|
|
|
|
|
2018-11-30 06:33:09 +08:00
|
|
|
// When compiling with -gmodules, also hash -fdebug-prefix-map as it
|
|
|
|
// affects the debug info in the PCM.
|
|
|
|
if (getCodeGenOpts().DebugTypeExtRefs)
|
|
|
|
for (const auto &KeyValue : getCodeGenOpts().DebugPrefixMap)
|
|
|
|
code = hash_combine(code, KeyValue.first, KeyValue.second);
|
|
|
|
|
2017-06-02 04:01:01 +08:00
|
|
|
// Extend the signature with the enabled sanitizers, if at least one is
|
|
|
|
// enabled. Sanitizers which cannot affect AST generation aren't hashed.
|
|
|
|
SanitizerSet SanHash = LangOpts->Sanitize;
|
|
|
|
SanHash.clear(getPPTransparentSanitizers());
|
|
|
|
if (!SanHash.empty())
|
|
|
|
code = hash_combine(code, SanHash.Mask);
|
|
|
|
|
2012-11-06 03:45:09 +08:00
|
|
|
return llvm::APInt(64, code).toString(36, /*Signed=*/false);
|
2011-09-14 07:15:45 +08:00
|
|
|
}
|
2013-06-15 01:17:23 +08:00
|
|
|
|
Add an option to allow Clang verify source files for a module only once during
the build
When Clang loads the module, it verifies the user source files that the module
was built from. If any file was changed, the module is rebuilt. There are two
problems with this:
1. correctness: we don't verify system files (there are too many of them, and
stat'ing all of them would take a lot of time);
2. performance: the same module file is verified again and again during a
single build.
This change allows the build system to optimize source file verification. The
idea is based on the fact that while the project is being built, the source
files don't change. This allows us to verify the module only once during a
single build session. The build system passes a flag,
-fbuild-session-timestamp=, to inform Clang of the time when the build started.
The build system also requests to enable this feature by passing
-fmodules-validate-once-per-build-session. If these flags are not passed, the
behavior is not changed. When Clang verifies the module the first time, it
writes out a timestamp file. Then, when Clang loads the module the second
time, it finds a timestamp file, so it can compare the verification timestamp
of the module with the time when the build started. If the verification
timestamp is too old, the module is verified again, and the timestamp file is
updated.
llvm-svn: 201224
2014-02-12 18:33:14 +08:00
|
|
|
template<typename IntTy>
|
|
|
|
static IntTy getLastArgIntValueImpl(const ArgList &Args, OptSpecifier Id,
|
|
|
|
IntTy Default,
|
|
|
|
DiagnosticsEngine *Diags) {
|
|
|
|
IntTy Res = Default;
|
2013-06-15 01:17:23 +08:00
|
|
|
if (Arg *A = Args.getLastArg(Id)) {
|
|
|
|
if (StringRef(A->getValue()).getAsInteger(10, Res)) {
|
|
|
|
if (Diags)
|
|
|
|
Diags->Report(diag::err_drv_invalid_int_value) << A->getAsString(Args)
|
|
|
|
<< A->getValue();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Res;
|
|
|
|
}
|
2013-12-27 16:11:08 +08:00
|
|
|
|
2018-03-27 05:45:04 +08:00
|
|
|
namespace clang {
|
Add an option to allow Clang verify source files for a module only once during
the build
When Clang loads the module, it verifies the user source files that the module
was built from. If any file was changed, the module is rebuilt. There are two
problems with this:
1. correctness: we don't verify system files (there are too many of them, and
stat'ing all of them would take a lot of time);
2. performance: the same module file is verified again and again during a
single build.
This change allows the build system to optimize source file verification. The
idea is based on the fact that while the project is being built, the source
files don't change. This allows us to verify the module only once during a
single build session. The build system passes a flag,
-fbuild-session-timestamp=, to inform Clang of the time when the build started.
The build system also requests to enable this feature by passing
-fmodules-validate-once-per-build-session. If these flags are not passed, the
behavior is not changed. When Clang verifies the module the first time, it
writes out a timestamp file. Then, when Clang loads the module the second
time, it finds a timestamp file, so it can compare the verification timestamp
of the module with the time when the build started. If the verification
timestamp is too old, the module is verified again, and the timestamp file is
updated.
llvm-svn: 201224
2014-02-12 18:33:14 +08:00
|
|
|
|
|
|
|
// Declared in clang/Frontend/Utils.h.
|
|
|
|
int getLastArgIntValue(const ArgList &Args, OptSpecifier Id, int Default,
|
|
|
|
DiagnosticsEngine *Diags) {
|
|
|
|
return getLastArgIntValueImpl<int>(Args, Id, Default, Diags);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t getLastArgUInt64Value(const ArgList &Args, OptSpecifier Id,
|
|
|
|
uint64_t Default,
|
|
|
|
DiagnosticsEngine *Diags) {
|
|
|
|
return getLastArgIntValueImpl<uint64_t>(Args, Id, Default, Diags);
|
|
|
|
}
|
|
|
|
|
2018-10-10 21:27:25 +08:00
|
|
|
IntrusiveRefCntPtr<llvm::vfs::FileSystem>
|
2014-04-16 02:16:25 +08:00
|
|
|
createVFSFromCompilerInvocation(const CompilerInvocation &CI,
|
|
|
|
DiagnosticsEngine &Diags) {
|
2018-10-10 21:27:25 +08:00
|
|
|
return createVFSFromCompilerInvocation(CI, Diags,
|
|
|
|
llvm::vfs::getRealFileSystem());
|
2017-05-23 19:37:52 +08:00
|
|
|
}
|
|
|
|
|
2018-10-10 21:27:25 +08:00
|
|
|
IntrusiveRefCntPtr<llvm::vfs::FileSystem> createVFSFromCompilerInvocation(
|
|
|
|
const CompilerInvocation &CI, DiagnosticsEngine &Diags,
|
|
|
|
IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS) {
|
2014-04-16 02:16:25 +08:00
|
|
|
if (CI.getHeaderSearchOpts().VFSOverlayFiles.empty())
|
2017-05-23 19:37:52 +08:00
|
|
|
return BaseFS;
|
2014-04-16 02:16:25 +08:00
|
|
|
|
2018-10-27 06:16:24 +08:00
|
|
|
IntrusiveRefCntPtr<llvm::vfs::FileSystem> Result = BaseFS;
|
2014-04-16 02:16:25 +08:00
|
|
|
// earlier vfs files are on the bottom
|
2018-03-27 05:45:04 +08:00
|
|
|
for (const auto &File : CI.getHeaderSearchOpts().VFSOverlayFiles) {
|
2014-07-07 01:43:24 +08:00
|
|
|
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =
|
2018-10-27 06:16:24 +08:00
|
|
|
Result->getBufferForFile(File);
|
2014-07-07 01:43:24 +08:00
|
|
|
if (!Buffer) {
|
2014-04-16 02:16:25 +08:00
|
|
|
Diags.Report(diag::err_missing_vfs_overlay_file) << File;
|
2018-03-24 01:37:27 +08:00
|
|
|
continue;
|
2014-04-16 02:16:25 +08:00
|
|
|
}
|
|
|
|
|
2018-10-10 21:27:25 +08:00
|
|
|
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = llvm::vfs::getVFSFromYAML(
|
2018-10-27 06:16:24 +08:00
|
|
|
std::move(Buffer.get()), /*DiagHandler*/ nullptr, File,
|
|
|
|
/*DiagContext*/ nullptr, Result);
|
|
|
|
if (!FS) {
|
2014-04-16 02:16:25 +08:00
|
|
|
Diags.Report(diag::err_invalid_vfs_overlay) << File;
|
2018-10-27 06:16:24 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
Result = FS;
|
2014-04-16 02:16:25 +08:00
|
|
|
}
|
2018-10-27 06:16:24 +08:00
|
|
|
return Result;
|
2013-06-15 01:17:23 +08:00
|
|
|
}
|
2018-03-27 05:45:04 +08:00
|
|
|
|
|
|
|
} // namespace clang
|