Frontend: Parse diagnostic options earlier.

Diagnostics may be emitted while parsing command line arguments. This implies
that the options which affect how diagnostics are emitted and presented need to
be parsed first.
This commit is contained in:
Allan Shortlidge
2025-01-14 23:18:40 -08:00
parent 29bcd2caa0
commit 4ea157efdb
4 changed files with 78 additions and 45 deletions

View File

@@ -20,6 +20,7 @@
#include "swift/Basic/Assertions.h"
#include "swift/Basic/Feature.h"
#include "swift/Basic/Platform.h"
#include "swift/Basic/Version.h"
#include "swift/Option/Options.h"
#include "swift/Option/SanitizerOptions.h"
#include "swift/Parse/Lexer.h"
@@ -92,20 +93,6 @@ void CompilerInvocation::setMainExecutablePath(StringRef Path) {
llvm::sys::path::remove_filename(clangPath);
llvm::sys::path::append(clangPath, "clang");
ClangImporterOpts.clangPath = std::string(clangPath);
llvm::SmallString<128> DiagnosticDocsPath(Path);
llvm::sys::path::remove_filename(DiagnosticDocsPath); // Remove /swift
llvm::sys::path::remove_filename(DiagnosticDocsPath); // Remove /bin
llvm::sys::path::append(DiagnosticDocsPath, "share", "doc", "swift",
"diagnostics");
DiagnosticOpts.DiagnosticDocumentationPath = std::string(DiagnosticDocsPath.str());
// Compute the path to the diagnostic translations in the toolchain/build.
llvm::SmallString<128> DiagnosticMessagesDir(Path);
llvm::sys::path::remove_filename(DiagnosticMessagesDir); // Remove /swift
llvm::sys::path::remove_filename(DiagnosticMessagesDir); // Remove /bin
llvm::sys::path::append(DiagnosticMessagesDir, "share", "swift", "diagnostics");
DiagnosticOpts.LocalizationPath = std::string(DiagnosticMessagesDir.str());
}
static std::string
@@ -2369,6 +2356,9 @@ static bool ParseSearchPathArgs(SearchPathOptions &Opts, ArgList &Args,
static bool ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
DiagnosticEngine &Diags) {
// NOTE: This executes at the beginning of parsing the command line and cannot
// depend on the results of parsing other options.
using namespace options;
if (Args.hasArg(OPT_verify))
@@ -2492,6 +2482,56 @@ static bool ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
return false;
}
static void configureDiagnosticEngine(
const DiagnosticOptions &Options,
std::optional<version::Version> effectiveLanguageVersion,
StringRef mainExecutablePath, DiagnosticEngine &Diagnostics) {
if (Options.ShowDiagnosticsAfterFatalError) {
Diagnostics.setShowDiagnosticsAfterFatalError();
}
if (Options.SuppressWarnings) {
Diagnostics.setSuppressWarnings(true);
}
if (Options.SuppressRemarks) {
Diagnostics.setSuppressRemarks(true);
}
Diagnostics.setWarningsAsErrorsRules(Options.WarningsAsErrorsRules);
Diagnostics.setPrintDiagnosticNamesMode(Options.PrintDiagnosticNames);
std::string docsPath = Options.DiagnosticDocumentationPath;
if (docsPath.empty()) {
// Default to a location relative to the compiler.
llvm::SmallString<128> docsPathBuffer(mainExecutablePath);
llvm::sys::path::remove_filename(docsPathBuffer); // Remove /swift
llvm::sys::path::remove_filename(docsPathBuffer); // Remove /bin
llvm::sys::path::append(docsPathBuffer, "share", "doc", "swift",
"diagnostics");
docsPath = docsPathBuffer.str();
}
Diagnostics.setDiagnosticDocumentationPath(docsPath);
if (!Options.LocalizationCode.empty()) {
std::string locPath = Options.LocalizationPath;
if (locPath.empty()) {
llvm::SmallString<128> locPathBuffer(mainExecutablePath);
llvm::sys::path::remove_filename(locPathBuffer); // Remove /swift
llvm::sys::path::remove_filename(locPathBuffer); // Remove /bin
llvm::sys::path::append(locPathBuffer, "share", "swift", "diagnostics");
locPath = locPathBuffer.str();
}
Diagnostics.setLocalization(Options.LocalizationCode, locPath);
}
if (effectiveLanguageVersion)
Diagnostics.setLanguageVersion(*effectiveLanguageVersion);
}
/// Configures the diagnostic engine for the invocation's options.
void CompilerInvocation::setUpDiagnosticEngine(DiagnosticEngine &diags) {
configureDiagnosticEngine(DiagnosticOpts, LangOpts.EffectiveLanguageVersion,
FrontendOpts.MainExecutablePath, diags);
}
/// Parse -enforce-exclusivity=... options
void parseExclusivityEnforcementOptions(const llvm::opt::Arg *A,
SILOptions &Opts,
@@ -3742,6 +3782,16 @@ bool CompilerInvocation::parseArgs(
return true;
}
// Parse options that control diagnostic behavior as early as possible, so
// that they can influence the behavior of diagnostics emitted during the
// rest of parsing.
if (ParseDiagnosticArgs(DiagnosticOpts, ParsedArgs, Diags)) {
return true;
}
configureDiagnosticEngine(DiagnosticOpts,
/*effectiveLanguageVersion=*/std::nullopt,
mainExecutablePath, Diags);
ParseAssertionArgs(ParsedArgs);
if (ParseFrontendArgs(FrontendOpts, ParsedArgs, Diags,
@@ -3796,10 +3846,6 @@ bool CompilerInvocation::parseArgs(
return true;
}
if (ParseDiagnosticArgs(DiagnosticOpts, ParsedArgs, Diags)) {
return true;
}
if (ParseMigratorArgs(MigratorOpts, LangOpts, FrontendOpts,
SearchPathOpts.RuntimeResourcePath, ParsedArgs, Diags)) {
return true;