[clang] eb581fc - [clang][cli] Generate and round-trip Diagnostic options
Jan Svoboda via cfe-commits
cfe-commits at lists.llvm.org
Wed Feb 10 03:44:57 PST 2021
Author: Jan Svoboda
Date: 2021-02-10T12:44:49+01:00
New Revision: eb581fc3241111688ee814170c92fb49c0c4cf61
URL: https://github.com/llvm/llvm-project/commit/eb581fc3241111688ee814170c92fb49c0c4cf61
DIFF: https://github.com/llvm/llvm-project/commit/eb581fc3241111688ee814170c92fb49c0c4cf61.diff
LOG: [clang][cli] Generate and round-trip Diagnostic options
This patch implements generation of remaining diagnostic options and tests it by performing parse-generate-parse round trip.
Reviewed By: dexonsmith
Differential Revision: https://reviews.llvm.org/D96274
Added:
Modified:
clang/include/clang/Driver/Options.td
clang/include/clang/Frontend/CompilerInvocation.h
clang/lib/Frontend/CompilerInvocation.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 563c85588af3..30f518a1a874 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4816,8 +4816,7 @@ def fcaret_diagnostics_max_lines :
def verify_EQ : CommaJoined<["-"], "verify=">,
MetaVarName<"<prefixes>">,
HelpText<"Verify diagnostic output using comment directives that start with"
- " prefixes in the comma-separated sequence <prefixes>">,
- MarshallingInfoStringVector<DiagnosticOpts<"VerifyPrefixes">>;
+ " prefixes in the comma-separated sequence <prefixes>">;
def verify : Flag<["-"], "verify">,
HelpText<"Equivalent to -verify=expected">;
def verify_ignore_unexpected : Flag<["-"], "verify-ignore-unexpected">,
diff --git a/clang/include/clang/Frontend/CompilerInvocation.h b/clang/include/clang/Frontend/CompilerInvocation.h
index 8cd512cbfd89..bf85cc755085 100644
--- a/clang/include/clang/Frontend/CompilerInvocation.h
+++ b/clang/include/clang/Frontend/CompilerInvocation.h
@@ -248,6 +248,18 @@ class CompilerInvocation : public CompilerInvocationBase {
bool parseSimpleArgs(const llvm::opt::ArgList &Args,
DiagnosticsEngine &Diags);
+ /// Parse command line options from DiagnosticOptions.
+ static bool ParseDiagnosticArgsRoundTrip(CompilerInvocation &Res,
+ DiagnosticOptions &Opts,
+ llvm::opt::ArgList &Args,
+ DiagnosticsEngine *Diags = nullptr,
+ bool DefaultDiagColor = true);
+
+ /// Generate command line options from DiagnosticOptions.
+ static void GenerateDiagnosticArgs(const DiagnosticOptions &Opts,
+ SmallVectorImpl<const char *> &Args,
+ StringAllocator SA, bool DefaultDiagColor);
+
/// Parse command line options that map to LangOptions.
static bool ParseLangArgsImpl(LangOptions &Opts, llvm::opt::ArgList &Args,
InputKind IK, const llvm::Triple &T,
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 3fa2331e2598..a0a2c4238423 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -731,17 +731,17 @@ static void addDiagnosticArgs(ArgList &Args, OptSpecifier Group,
for (auto *A : Args.filtered(Group)) {
if (A->getOption().getKind() == Option::FlagClass) {
// 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.
+ // its name (minus the "W" or "R" at the beginning) to the diagnostics.
Diagnostics.push_back(
std::string(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.
+ // This is -Wfoo= or -Rfoo=, where foo is the name of the diagnostic
+ // group. Add only the group name to the diagnostics.
Diagnostics.push_back(
std::string(A->getOption().getName().drop_front(1).rtrim("=-")));
} else {
// Otherwise, add its value (for OPT_W_Joined and similar).
- for (const auto *Arg : A->getValues())
- Diagnostics.emplace_back(Arg);
+ Diagnostics.push_back(A->getValue());
}
}
}
@@ -2174,6 +2174,63 @@ bool CompilerInvocation::parseSimpleArgs(const ArgList &Args,
return Success;
}
+void CompilerInvocation::GenerateDiagnosticArgs(
+ const DiagnosticOptions &Opts, SmallVectorImpl<const char *> &Args,
+ StringAllocator SA, bool DefaultDiagColor) {
+ const DiagnosticOptions *DiagnosticOpts = &Opts;
+#define DIAG_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 DIAG_OPTION_WITH_MARSHALLING
+
+ if (!Opts.DiagnosticSerializationFile.empty())
+ GenerateArg(Args, OPT_diagnostic_serialized_file,
+ Opts.DiagnosticSerializationFile, SA);
+
+ if (Opts.ShowColors)
+ GenerateArg(Args, OPT_fcolor_diagnostics, SA);
+
+ if (Opts.VerifyDiagnostics &&
+ llvm::is_contained(Opts.VerifyPrefixes, "expected"))
+ GenerateArg(Args, OPT_verify, SA);
+
+ for (const auto &Prefix : Opts.VerifyPrefixes)
+ if (Prefix != "expected")
+ GenerateArg(Args, OPT_verify_EQ, Prefix, SA);
+
+ DiagnosticLevelMask VIU = Opts.getVerifyIgnoreUnexpected();
+ if (VIU == DiagnosticLevelMask::None) {
+ // This is the default, don't generate anything.
+ } else if (VIU == DiagnosticLevelMask::All) {
+ GenerateArg(Args, OPT_verify_ignore_unexpected, SA);
+ } else {
+ if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Note) != 0)
+ GenerateArg(Args, OPT_verify_ignore_unexpected_EQ, "note", SA);
+ if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Remark) != 0)
+ GenerateArg(Args, OPT_verify_ignore_unexpected_EQ, "remark", SA);
+ if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Warning) != 0)
+ GenerateArg(Args, OPT_verify_ignore_unexpected_EQ, "warning", SA);
+ if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Error) != 0)
+ GenerateArg(Args, OPT_verify_ignore_unexpected_EQ, "error", SA);
+ }
+
+ for (const auto &Warning : Opts.Warnings) {
+ // This option is automatically generated from UndefPrefixes.
+ if (Warning == "undef-prefix")
+ continue;
+ Args.push_back(SA(StringRef("-W") + Warning));
+ }
+
+ for (const auto &Remark : Opts.Remarks)
+ Args.push_back(SA(StringRef("-R") + Remark));
+}
+
bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
DiagnosticsEngine *Diags,
bool DefaultDiagColor) {
@@ -2209,6 +2266,7 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
Opts.ShowColors = parseShowColorsArgs(Args, DefaultDiagColor);
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
@@ -2238,6 +2296,45 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
return Success;
}
+bool CompilerInvocation::ParseDiagnosticArgsRoundTrip(CompilerInvocation &Res,
+ DiagnosticOptions &Opts,
+ ArgList &Args,
+ DiagnosticsEngine *Diags,
+ bool DefaultDiagColor) {
+ IntrusiveRefCntPtr<DiagnosticOptions> DummyOpts(new DiagnosticOptions);
+
+ return RoundTrip(
+ [DefaultDiagColor](CompilerInvocation &Res, ArgList &Args,
+ DiagnosticsEngine &Diags) {
+ // Query the options might not get queried properly during parsing, but
+ // should be generated from DiagnosticOptions.
+
+ Args.getLastArg(OPT_fcolor_diagnostics);
+ Args.getLastArg(OPT_fno_color_diagnostics);
+ Args.getLastArg(OPT_fdiagnostics_color);
+ Args.getLastArg(OPT_fno_diagnostics_color);
+ Args.getLastArg(OPT_fdiagnostics_color_EQ);
+
+ for (auto *A : Args.filtered(OPT_W_Group))
+ Args.getLastArg(A->getOption().getID());
+ for (auto *A : Args.filtered(OPT_R_Group))
+ Args.getLastArg(A->getOption().getID());
+
+ return clang::ParseDiagnosticArgs(Res.getDiagnosticOpts(), Args, &Diags,
+ DefaultDiagColor);
+ },
+ [DefaultDiagColor](CompilerInvocation &Res,
+ SmallVectorImpl<const char *> &Args,
+ CompilerInvocation::StringAllocator SA) {
+ GenerateDiagnosticArgs(Res.getDiagnosticOpts(), Args, SA,
+ DefaultDiagColor);
+ },
+ [&DummyOpts](CompilerInvocation &Res) {
+ Res.DiagnosticOpts.swap(DummyOpts);
+ },
+ Res, Args, *Diags, "DiagnosticOptions");
+}
+
/// Parse the argument to the -ftest-module-file-extension
/// command-line argument.
///
@@ -4393,8 +4490,9 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
Success &= Res.parseSimpleArgs(Args, Diags);
Success &= ParseAnalyzerArgs(Res, *Res.getAnalyzerOpts(), Args, Diags);
- Success &= ParseDiagnosticArgs(Res.getDiagnosticOpts(), Args, &Diags,
- /*DefaultDiagColor=*/false);
+ Success &=
+ ParseDiagnosticArgsRoundTrip(Res, Res.getDiagnosticOpts(), Args, &Diags,
+ /*DefaultDiagColor=*/false);
Success &= ParseFrontendArgs(Res, Res.getFrontendOpts(), Args, Diags,
LangOpts.IsHeaderFile);
// FIXME: We shouldn't have to pass the DashX option around here
@@ -4613,17 +4711,13 @@ void CompilerInvocation::generateCC1CommandLine(
ALWAYS_EMIT, this->KEYPATH, DEFAULT_VALUE, \
IMPLIED_CHECK, IMPLIED_VALUE, DENORMALIZER, \
EXTRACTOR, TABLE_INDEX)
-
-#define DIAG_OPTION_WITH_MARSHALLING OPTION_WITH_MARSHALLING
-
#include "clang/Driver/Options.inc"
-
-#undef DIAG_OPTION_WITH_MARSHALLING
#undef OPTION_WITH_MARSHALLING
llvm::Triple T(TargetOpts->Triple);
GenerateAnalyzerArgs(*AnalyzerOpts, Args, SA);
+ GenerateDiagnosticArgs(*DiagnosticOpts, Args, SA, false);
GenerateFrontendArgs(FrontendOpts, Args, SA, LangOpts->IsHeaderFile);
GenerateTargetArgs(*TargetOpts, Args, SA);
GenerateHeaderSearchArgs(*HeaderSearchOpts, Args, SA);
More information about the cfe-commits
mailing list