[clang] 0e07383 - [clang][cli] Generate and round-trip analyzer options
Jan Svoboda via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 8 00:26:11 PST 2021
Author: Jan Svoboda
Date: 2021-02-08T09:26:01+01:00
New Revision: 0e07383433d0edc1f53410ce42fae437e1a8f967
URL: https://github.com/llvm/llvm-project/commit/0e07383433d0edc1f53410ce42fae437e1a8f967
DIFF: https://github.com/llvm/llvm-project/commit/0e07383433d0edc1f53410ce42fae437e1a8f967.diff
LOG: [clang][cli] Generate and round-trip analyzer options
This patch implements generation of remaining analyzer options and tests it by performing parse-generate-parse round trip.
Reviewed By: dexonsmith
Differential Revision: https://reviews.llvm.org/D95369
Added:
Modified:
clang/include/clang/Driver/Options.td
clang/lib/Frontend/CompilerInvocation.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 7bd9a8ab40dc8..cbd501ca2a74b 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -262,7 +262,7 @@ class PreprocessorOpts<string base>
class FileSystemOpts<string base>
: KeyPathAndMacro<"FileSystemOpts.", base> {}
class AnalyzerOpts<string base>
- : KeyPathAndMacro<"AnalyzerOpts->", base> {}
+ : KeyPathAndMacro<"AnalyzerOpts->", base, "ANALYZER_"> {}
class MigratorOpts<string base>
: KeyPathAndMacro<"MigratorOpts.", base> {}
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 0a12705a92610..f93f10cf0988b 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -760,9 +760,121 @@ static void getAllNoBuiltinFuncValues(ArgList &Args,
Funcs.insert(Funcs.end(), Values.begin(), Values.end());
}
-static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
- DiagnosticsEngine &Diags) {
+static void GenerateAnalyzerArgs(AnalyzerOptions &Opts,
+ SmallVectorImpl<const char *> &Args,
+ CompilerInvocation::StringAllocator SA) {
+ const AnalyzerOptions *AnalyzerOpts = &Opts;
+
+#define ANALYZER_OPTION_WITH_MARSHALLING( \
+ PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
+ DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
+ MERGER, EXTRACTOR, TABLE_INDEX) \
+ GENERATE_OPTION_WITH_MARSHALLING( \
+ Args, SA, KIND, FLAGS, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, DENORMALIZER, EXTRACTOR, TABLE_INDEX)
+#include "clang/Driver/Options.inc"
+#undef ANALYZER_OPTION_WITH_MARSHALLING
+
+ if (Opts.AnalysisStoreOpt != RegionStoreModel) {
+ switch (Opts.AnalysisStoreOpt) {
+#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) \
+ case NAME##Model: \
+ GenerateArg(Args, OPT_analyzer_store, CMDFLAG, SA); \
+ break;
+#include "clang/StaticAnalyzer/Core/Analyses.def"
+ default:
+ llvm_unreachable("Tried to generate unknown analysis store.");
+ }
+ }
+
+ if (Opts.AnalysisConstraintsOpt != RangeConstraintsModel) {
+ switch (Opts.AnalysisConstraintsOpt) {
+#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \
+ case NAME##Model: \
+ GenerateArg(Args, OPT_analyzer_constraints, CMDFLAG, SA); \
+ break;
+#include "clang/StaticAnalyzer/Core/Analyses.def"
+ default:
+ llvm_unreachable("Tried to generate unknown analysis constraint.");
+ }
+ }
+
+ if (Opts.AnalysisDiagOpt != PD_HTML) {
+ switch (Opts.AnalysisDiagOpt) {
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) \
+ case PD_##NAME: \
+ GenerateArg(Args, OPT_analyzer_output, CMDFLAG, SA); \
+ break;
+#include "clang/StaticAnalyzer/Core/Analyses.def"
+ default:
+ llvm_unreachable("Tried to generate unknown analysis diagnostic client.");
+ }
+ }
+
+ if (Opts.AnalysisPurgeOpt != PurgeStmt) {
+ switch (Opts.AnalysisPurgeOpt) {
+#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) \
+ case NAME: \
+ GenerateArg(Args, OPT_analyzer_purge, CMDFLAG, SA); \
+ break;
+#include "clang/StaticAnalyzer/Core/Analyses.def"
+ default:
+ llvm_unreachable("Tried to generate unknown analysis purge mode.");
+ }
+ }
+
+ if (Opts.InliningMode != NoRedundancy) {
+ switch (Opts.InliningMode) {
+#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) \
+ case NAME: \
+ GenerateArg(Args, OPT_analyzer_inlining_mode, CMDFLAG, SA); \
+ break;
+#include "clang/StaticAnalyzer/Core/Analyses.def"
+ default:
+ llvm_unreachable("Tried to generate unknown analysis inlining mode.");
+ }
+ }
+
+ for (const auto &CP : Opts.CheckersAndPackages) {
+ OptSpecifier Opt =
+ CP.second ? OPT_analyzer_checker : OPT_analyzer_disable_checker;
+ GenerateArg(Args, Opt, CP.first, SA);
+ }
+
+ AnalyzerOptions ConfigOpts;
+ parseAnalyzerConfigs(ConfigOpts, nullptr);
+
+ for (const auto &C : Opts.Config) {
+ // Don't generate anything that came from parseAnalyzerConfigs. It would be
+ // redundant and may not be valid on the command line.
+ auto Entry = ConfigOpts.Config.find(C.getKey());
+ if (Entry != ConfigOpts.Config.end() && Entry->getValue() == C.getValue())
+ continue;
+
+ GenerateArg(Args, OPT_analyzer_config, C.getKey() + "=" + C.getValue(), SA);
+ }
+
+ // Nothing to generate for FullCompilerInvocation.
+}
+
+static bool ParseAnalyzerArgsImpl(AnalyzerOptions &Opts, ArgList &Args,
+ DiagnosticsEngine &Diags) {
+ AnalyzerOptions *AnalyzerOpts = &Opts;
bool Success = true;
+
+#define ANALYZER_OPTION_WITH_MARSHALLING( \
+ PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
+ DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
+ MERGER, EXTRACTOR, TABLE_INDEX) \
+ PARSE_OPTION_WITH_MARSHALLING(Args, Diags, Success, ID, FLAGS, PARAM, \
+ SHOULD_PARSE, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, \
+ MERGER, TABLE_INDEX)
+#include "clang/Driver/Options.inc"
+#undef ANALYZER_OPTION_WITH_MARSHALLING
+
if (Arg *A = Args.getLastArg(OPT_analyzer_store)) {
StringRef Name = A->getValue();
AnalysisStores Value = llvm::StringSwitch<AnalysisStores>(Name)
@@ -886,8 +998,10 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
// TODO: Check checker options too, possibly in CheckerRegistry.
// Leave unknown non-checker configs unclaimed.
if (!key.contains(":") && Opts.isUnknownAnalyzerConfig(key)) {
- if (Opts.ShouldEmitErrorsOnInvalidConfigValue)
+ if (Opts.ShouldEmitErrorsOnInvalidConfigValue) {
Diags.Report(diag::err_analyzer_config_unknown) << key;
+ Success = false;
+ }
continue;
}
@@ -912,6 +1026,24 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
return Success;
}
+static bool ParseAnalyzerArgs(CompilerInvocation &Res, AnalyzerOptions &Opts,
+ ArgList &Args, DiagnosticsEngine &Diags) {
+ auto DummyOpts = IntrusiveRefCntPtr<AnalyzerOptions>(new AnalyzerOptions());
+
+ return RoundTrip(
+ [](CompilerInvocation &Res, ArgList &Args, DiagnosticsEngine &Diags) {
+ return ParseAnalyzerArgsImpl(*Res.getAnalyzerOpts(), Args, Diags);
+ },
+ [](CompilerInvocation &Res, SmallVectorImpl<const char *> &Args,
+ CompilerInvocation::StringAllocator SA) {
+ GenerateAnalyzerArgs(*Res.getAnalyzerOpts(), Args, SA);
+ },
+ [&DummyOpts](CompilerInvocation &Res) {
+ Res.getAnalyzerOpts().swap(DummyOpts);
+ },
+ Res, Args, Diags, "AnalyzerOptions");
+}
+
static StringRef getStringOption(AnalyzerOptions::ConfigTable &Config,
StringRef OptionName, StringRef DefaultVal) {
return Config.insert({OptionName, std::string(DefaultVal)}).first->second;
@@ -3123,7 +3255,7 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
Success &= Res.parseSimpleArgs(Args, Diags);
- Success &= ParseAnalyzerArgs(*Res.getAnalyzerOpts(), Args, Diags);
+ Success &= ParseAnalyzerArgs(Res, *Res.getAnalyzerOpts(), Args, Diags);
ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), Args);
if (!Res.getDependencyOutputOpts().OutputFile.empty() &&
Res.getDependencyOutputOpts().Targets.empty()) {
@@ -3351,6 +3483,7 @@ void CompilerInvocation::generateCC1CommandLine(
#undef DIAG_OPTION_WITH_MARSHALLING
#undef OPTION_WITH_MARSHALLING
+ GenerateAnalyzerArgs(*AnalyzerOpts, Args, SA);
GenerateHeaderSearchArgs(*HeaderSearchOpts, Args, SA);
GenerateLangArgs(*LangOpts, Args, SA);
}
More information about the cfe-commits
mailing list